diff options
62 files changed, 3546 insertions, 1267 deletions
diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt index 3136687adb57..ddca4c39e2de 100644 --- a/Documentation/devicetree/bindings/usb/dwc3.txt +++ b/Documentation/devicetree/bindings/usb/dwc3.txt @@ -60,6 +60,7 @@ Optional properties: - snps,num-normal-evt-buffs: If present, specifies number of normal event buffers. Default is 1. - snps,num-gsi-evt-buffs: If present, specifies number of GSI based hardware accelerated event buffers. 1 event buffer is needed per h/w accelerated endpoint. + - xhci-imod-value: Interrupt moderation interval for host mode (in increments of 250nsec). This is usually a subnode to DWC3 glue to which it is connected. @@ -74,4 +75,5 @@ dwc3@4a030000 { tx-fifo-resize; snps,usb3-u1u2-disable; snps,num-gsi-evt-buffs = <0x2>; + xhci-imod-value = <4000>; }; diff --git a/arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts b/arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts index bc18fb54400f..78fdba4fdb9b 100644 --- a/arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts +++ b/arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -25,6 +25,10 @@ status = "disabled"; }; +&msm_ath10k_wlan { + status = "enabled"; +}; + &mdss_mdp { qcom,mdss-pref-prim-intf = "hdmi"; }; diff --git a/arch/arm/boot/dts/qcom/msm-smb138x.dtsi b/arch/arm/boot/dts/qcom/msm-smb138x.dtsi index e6e04f19d7ea..2aa730898f75 100644 --- a/arch/arm/boot/dts/qcom/msm-smb138x.dtsi +++ b/arch/arm/boot/dts/qcom/msm-smb138x.dtsi @@ -57,8 +57,8 @@ die_temp@2 { reg = <2>; - qcom,scale = <(-1032)>; - qcom,offset = <344125>; + qcom,scale = <(-1306)>; + qcom,offset = <397904>; }; batt_i@3 { diff --git a/arch/arm/boot/dts/qcom/msm8998-camera.dtsi b/arch/arm/boot/dts/qcom/msm8998-camera.dtsi index f8dae210bc4e..c35ea886408d 100644 --- a/arch/arm/boot/dts/qcom/msm8998-camera.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-camera.dtsi @@ -51,8 +51,8 @@ "csi_src_clk", "csi_clk", "cphy_csid_clk", "csiphy_timer_src_clk", "csiphy_timer_clk", "camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk"; - qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 200000000 0 - 0 256000000 0>; + qcom,clock-rates = <0 0 0 0 0 0 274290000 0 0 200000000 0 + 0 274290000 0>; status = "ok"; }; @@ -86,8 +86,8 @@ "csi_src_clk", "csi_clk", "cphy_csid_clk", "csiphy_timer_src_clk", "csiphy_timer_clk", "camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk"; - qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 200000000 0 - 0 256000000 0>; + qcom,clock-rates = <0 0 0 0 0 0 274290000 0 0 200000000 0 + 0 274290000 0>; status = "ok"; }; @@ -121,8 +121,8 @@ "csi_src_clk", "csi_clk", "cphy_csid_clk", "csiphy_timer_src_clk", "csiphy_timer_clk", "camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk"; - qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 200000000 0 - 0 256000000 0>; + qcom,clock-rates = <0 0 0 0 0 0 274290000 0 0 200000000 0 + 0 274290000 0>; status = "ok"; }; @@ -159,7 +159,7 @@ "ispif_ahb_clk", "csi_src_clk", "csiphy_clk_src", "csi_clk", "csi_ahb_clk", "csi_rdi_clk", "csi_pix_clk", "cphy_csid_clk"; - qcom,clock-rates = <0 0 0 0 0 0 0 256000000 256000000 + qcom,clock-rates = <0 0 0 0 0 0 0 274290000 274290000 0 0 0 0 0>; status = "ok"; }; @@ -197,7 +197,7 @@ "ispif_ahb_clk", "csi_src_clk", "csiphy_clk_src", "csi_clk", "csi_ahb_clk", "csi_rdi_clk", "csi_pix_clk", "cphy_csid_clk"; - qcom,clock-rates = <0 0 0 0 0 0 0 256000000 256000000 + qcom,clock-rates = <0 0 0 0 0 0 0 274290000 274290000 0 0 0 0 0>; status = "ok"; }; @@ -235,7 +235,7 @@ "ispif_ahb_clk", "csi_src_clk", "csiphy_clk_src", "csi_clk", "csi_ahb_clk", "csi_rdi_clk", "csi_pix_clk", "cphy_csid_clk"; - qcom,clock-rates = <0 0 0 0 0 0 0 256000000 256000000 + qcom,clock-rates = <0 0 0 0 0 0 0 274290000 274290000 0 0 0 0 0>; status = "ok"; }; @@ -273,7 +273,7 @@ "ispif_ahb_clk", "csi_src_clk", "csiphy_clk_src", "csi_clk", "csi_ahb_clk", "csi_rdi_clk", "csi_pix_clk", "cphy_csid_clk"; - qcom,clock-rates = <0 0 0 0 0 0 0 256000000 256000000 + qcom,clock-rates = <0 0 0 0 0 0 0 274290000 274290000 0 0 0 0 0>; status = "ok"; }; diff --git a/arch/arm/boot/dts/qcom/msm8998-v2-camera.dtsi b/arch/arm/boot/dts/qcom/msm8998-v2-camera.dtsi index fdc452a47a46..93da11e66799 100644 --- a/arch/arm/boot/dts/qcom/msm8998-v2-camera.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-v2-camera.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -42,8 +42,8 @@ "csi_src_clk", "csi_clk", "cphy_csid_clk", "csiphy_timer_src_clk", "csiphy_timer_clk", "camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk"; - qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 200000000 0 - 0 256000000 0>; + qcom,clock-rates = <0 0 0 0 0 0 274290000 0 0 200000000 0 + 0 274290000 0>; status = "ok"; }; @@ -77,8 +77,8 @@ "csi_src_clk", "csi_clk", "cphy_csid_clk", "csiphy_timer_src_clk", "csiphy_timer_clk", "camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk"; - qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 200000000 0 - 0 256000000 0>; + qcom,clock-rates = <0 0 0 0 0 0 274290000 0 0 200000000 0 + 0 274290000 0>; status = "ok"; }; @@ -112,8 +112,8 @@ "csi_src_clk", "csi_clk", "cphy_csid_clk", "csiphy_timer_src_clk", "csiphy_timer_clk", "camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk"; - qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 200000000 0 - 0 256000000 0>; + qcom,clock-rates = <0 0 0 0 0 0 274290000 0 0 200000000 0 + 0 274290000 0>; status = "ok"; }; diff --git a/arch/arm/boot/dts/qcom/msm8998.dtsi b/arch/arm/boot/dts/qcom/msm8998.dtsi index 30679791006b..2e41f3a3567d 100644 --- a/arch/arm/boot/dts/qcom/msm8998.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998.dtsi @@ -3041,7 +3041,25 @@ }; - qcom,icnss@18800000 { + msm_ath10k_wlan: qcom,msm_ath10k_wlan@18000000 { + status = "disabled"; + compatible = "qcom,wcn3990-wifi"; + interrupts = + <0 413 0 /* CE0 */ >, + <0 414 0 /* CE1 */ >, + <0 415 0 /* CE2 */ >, + <0 416 0 /* CE3 */ >, + <0 417 0 /* CE4 */ >, + <0 418 0 /* CE5 */ >, + <0 420 0 /* CE6 */ >, + <0 421 0 /* CE7 */ >, + <0 422 0 /* CE8 */ >, + <0 423 0 /* CE9 */ >, + <0 424 0 /* CE10 */ >, + <0 425 0 /* CE11 */ >; + }; + + qcom,icnss@18800000 { compatible = "qcom,icnss"; reg = <0x18800000 0x800000>, <0xa0000000 0x10000000>, diff --git a/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi b/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi index 2232327f1302..af288ff26d06 100644 --- a/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi @@ -25,6 +25,27 @@ qcom,led-strings-list = [01 02]; }; +&ufsphy1 { + vdda-phy-supply = <&pm660l_l1>; + vdda-pll-supply = <&pm660_l10>; + vddp-ref-clk-supply = <&pm660_l1>; + vdda-phy-max-microamp = <51400>; + vdda-pll-max-microamp = <14200>; + 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 = <&pm660l_l4>; + vccq2-supply = <&pm660_l8>; + vcc-max-microamp = <500000>; + vccq2-max-microamp = <600000>; + status = "ok"; +}; + &soc { }; diff --git a/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi b/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi index b07a9190331b..a47f8419f41a 100644 --- a/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi @@ -26,6 +26,27 @@ pinctrl-0 = <&uart_console_active>; }; +&ufsphy1 { + vdda-phy-supply = <&pm660l_l1>; + vdda-pll-supply = <&pm660_l10>; + vddp-ref-clk-supply = <&pm660_l1>; + vdda-phy-max-microamp = <51400>; + vdda-pll-max-microamp = <14200>; + 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 = <&pm660l_l4>; + vccq2-supply = <&pm660_l8>; + vcc-max-microamp = <500000>; + vccq2-max-microamp = <600000>; + status = "ok"; +}; + &mem_client_3_size { qcom,peripheral-size = <0x500000>; }; diff --git a/arch/arm/boot/dts/qcom/sdm630-rumi.dts b/arch/arm/boot/dts/qcom/sdm630-rumi.dts index 2ea1af4da90c..018429a4ebb1 100644 --- a/arch/arm/boot/dts/qcom/sdm630-rumi.dts +++ b/arch/arm/boot/dts/qcom/sdm630-rumi.dts @@ -67,6 +67,27 @@ pinctrl-0 = <&uart_console_active>; }; +&ufsphy1 { + vdda-phy-supply = <&pm660l_l1>; + vdda-pll-supply = <&pm660_l10>; + vddp-ref-clk-supply = <&pm660_l1>; + vdda-phy-max-microamp = <51400>; + vdda-pll-max-microamp = <14200>; + 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 = <&pm660l_l4>; + vccq2-supply = <&pm660_l8>; + vcc-max-microamp = <500000>; + vccq2-max-microamp = <600000>; + status = "ok"; +}; + &clock_gcc { compatible = "qcom,dummycc"; clock-output-names = "gcc_clocks"; diff --git a/arch/arm/boot/dts/qcom/sdm630.dtsi b/arch/arm/boot/dts/qcom/sdm630.dtsi index 953c26f2622d..13aa096cd0e7 100644 --- a/arch/arm/boot/dts/qcom/sdm630.dtsi +++ b/arch/arm/boot/dts/qcom/sdm630.dtsi @@ -17,6 +17,7 @@ #include <dt-bindings/clock/qcom,rpmcc.h> #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/regulator/qcom,rpm-smd-regulator.h> +#include <dt-bindings/clock/qcom,cpu-osm.h> / { model = "Qualcomm Technologies, Inc. SDM630"; @@ -293,7 +294,7 @@ alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>; reusable; alignment = <0x0 0x400000>; - size = <0x0 0x400000>; + size = <0x0 0xa00000>; }; qseecom_mem: qseecom_region { @@ -939,6 +940,105 @@ qcom,ipa-advertise-sg-support; }; + clock_cpu: qcom,clk-cpu-630@179c0000 { + compatible = "qcom,clk-cpu-osm-sdm630"; + status = "disabled"; + reg = <0x179c0000 0x4000>, <0x17916000 0x1000>, + <0x17816000 0x1000>, <0x179d1000 0x1000>, + <0x00784130 0x8>; + reg-names = "osm", "pwrcl_pll", "perfcl_pll", + "apcs_common", "perfcl_efuse"; + + interrupts = <GIC_SPI 35 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 36 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "pwrcl-irq", "perfcl-irq"; + + qcom,pwrcl-speedbin0-v0 = + < 300000000 0x0004000f 0x01200020 0x1 1 >, + < 614400000 0x05040020 0x03200020 0x1 2 >, + < 883200000 0x0404002e 0x04250025 0x1 3 >, + < 1094400000 0x04040039 0x052e002e 0x2 4 >, + < 1382400000 0x04040048 0x07390039 0x2 5 >, + < 1536000000 0x04040050 0x08400040 0x3 6 >, + < 1728000000 0x0404005a 0x09480048 0x3 7 >, + < 1843200000 0x04040060 0x094c004c 0x3 8 >; + + qcom,perfcl-speedbin0-v0 = + < 300000000 0x0004000f 0x01200020 0x1 1 >, + < 787200000 0x05040029 0x04200020 0x1 2 >, + < 1113600000 0x0404003a 0x052e002e 0x1 3 >, + < 1344000000 0x04040046 0x07380038 0x2 4 >, + < 1516800000 0x0404004f 0x073f003f 0x2 5 >, + < 1670400000 0x04040057 0x08450045 0x2 6 >, + < 1881600000 0x04040062 0x094e004e 0x3 7 >, + < 2016000000 0x04040069 0x0a540054 0x3 8 >, + < 2150400000 0x04040070 0x0b590059 0x3 9 >, + < 2380800000 0x0404007c 0x0c630063 0x3 10 >; + + qcom,perfcl-speedbin1-v0 = + < 300000000 0x0004000f 0x01200020 0x1 1 >, + < 787200000 0x05040029 0x04200020 0x1 2 >, + < 1113600000 0x0404003a 0x052e002e 0x1 3 >, + < 1344000000 0x04040046 0x07380038 0x2 4 >, + < 1516800000 0x0404004f 0x073f003f 0x2 5 >, + < 1670400000 0x04040057 0x08450045 0x2 6 >, + < 1881600000 0x04040062 0x094e004e 0x3 7 >, + < 2016000000 0x04040069 0x0a540054 0x3 8 >, + < 2150400000 0x04040070 0x0b590059 0x3 8 >, + < 2208000000 0x04040073 0x0b5c005c 0x3 10 >; + + qcom,perfcl-speedbin2-v0 = + < 300000000 0x0004000f 0x01200020 0x1 1 >, + < 787200000 0x05040029 0x04200020 0x1 2 >, + < 1113600000 0x0404003a 0x052e002e 0x1 3 >, + < 1344000000 0x04040046 0x07380038 0x2 4 >, + < 1516800000 0x0404004f 0x073f003f 0x2 5 >, + < 1670400000 0x04040057 0x08450045 0x2 6 >, + < 1881600000 0x04040062 0x094e004e 0x3 7 >, + < 2016000000 0x04040069 0x0a540054 0x3 8 >, + < 2150400000 0x04040070 0x0b590059 0x3 9 >, + < 2380800000 0x0404007c 0x0c630063 0x3 10 >, + < 2515200000 0x04040083 0x0d680068 0x3 11 >; + + qcom,up-timer = <1000 1000>; + qcom,down-timer = <1000 1000>; + qcom,pc-override-index = <0 0>; + qcom,set-ret-inactive; + qcom,enable-llm-freq-vote; + qcom,llm-freq-up-timer = <327675 327675>; + qcom,llm-freq-down-timer = <327675 327675>; + qcom,enable-llm-volt-vote; + qcom,llm-volt-up-timer = <327675 327675>; + qcom,llm-volt-down-timer = <327675 327675>; + qcom,cc-reads = <10>; + qcom,cc-delay = <5>; + qcom,cc-factor = <100>; + qcom,osm-clk-rate = <200000000>; + qcom,xo-clk-rate = <19200000>; + + qcom,l-val-base = <0x17916004 0x17816004>; + qcom,apcs-itm-present = <0x179d143c 0x179d143c>; + qcom,apcs-pll-user-ctl = <0x1791600c 0x1781600c>; + qcom,apcs-cfg-rcgr = <0x17911054 0x17811054>; + qcom,apcs-cmd-rcgr = <0x17911050 0x17811050>; + qcom,apm-mode-ctl = <0x179d0004 0x179d0010>; + qcom,apm-ctrl-status = <0x179d000c 0x179d0018>; + + qcom,apm-threshold-voltage = <872000>; + qcom,boost-fsm-en; + qcom,safe-fsm-en; + qcom,ps-fsm-en; + qcom,droop-fsm-en; + qcom,wfx-fsm-en; + qcom,pc-fsm-en; + + clock-names = "aux_clk", "xo_a"; + clocks = <&clock_gcc HMSS_GPLL0_CLK_SRC>, + <&clock_rpmcc RPM_XO_A_CLK_SRC>; + + #clock-cells = <1>; + }; + qcom,ipc-spinlock@1f40000 { compatible = "qcom,ipc-spinlock-sfpb"; reg = <0x1f40000 0x8000>; @@ -956,6 +1056,41 @@ qcom,mpu-enabled; }; + qcom,msm-adsprpc-mem { + compatible = "qcom,msm-adsprpc-mem-region"; + memory-region = <&adsp_mem>; + }; + + qcom,msm_fastrpc { + compatible = "qcom,msm-fastrpc-adsp"; + qcom,fastrpc-glink; + + qcom,msm_fastrpc_compute_cb1 { + compatible = "qcom,msm-fastrpc-compute-cb"; + label = "adsprpc-smd"; + iommus = <&lpass_q6_smmu 3>; + dma-coherent; + }; + qcom,msm_fastrpc_compute_cb2 { + compatible = "qcom,msm-fastrpc-compute-cb"; + label = "adsprpc-smd"; + iommus = <&lpass_q6_smmu 7>; + dma-coherent; + }; + qcom,msm_fastrpc_compute_cb3 { + compatible = "qcom,msm-fastrpc-compute-cb"; + label = "adsprpc-smd"; + iommus = <&lpass_q6_smmu 8>; + dma-coherent; + }; + qcom,msm_fastrpc_compute_cb4 { + compatible = "qcom,msm-fastrpc-compute-cb"; + label = "adsprpc-smd"; + iommus = <&lpass_q6_smmu 9>; + dma-coherent; + }; + }; + dcc: dcc@10b3000 { compatible = "qcom,dcc"; reg = <0x10b3000 0x1000>, diff --git a/arch/arm/boot/dts/qcom/sdm660-common.dtsi b/arch/arm/boot/dts/qcom/sdm660-common.dtsi index a5e66f38df3c..5a0997faf133 100644 --- a/arch/arm/boot/dts/qcom/sdm660-common.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-common.dtsi @@ -11,6 +11,89 @@ */ &soc { + ufsphy1: ufsphy@1da7000 { + compatible = "qcom,ufs-phy-qmp-v3-660"; + reg = <0x1da7000 0xdb8>; + reg-names = "phy_mem"; + #phy-cells = <0>; + clock-names = "ref_clk_src", + "ref_clk", + "ref_aux_clk"; + clocks = <&clock_rpmcc RPM_LN_BB_CLK1>, + <&clock_gcc GCC_UFS_CLKREF_CLK>, + <&clock_gcc GCC_UFS_PHY_AUX_CLK>; + status = "disabled"; + }; + + ufs1: ufshc@1da4000 { + compatible = "qcom,ufshc"; + reg = <0x1da4000 0x3000>; + interrupts = <0 265 0>; + phys = <&ufsphy1>; + phy-names = "ufsphy"; + + clock-names = + "core_clk", + "bus_aggr_clk", + "iface_clk", + "core_clk_unipro", + "core_clk_ice", + "ref_clk", + "tx_lane0_sync_clk", + "rx_lane0_sync_clk"; + clocks = + <&clock_gcc GCC_UFS_AXI_CLK>, + <&clock_gcc GCC_AGGRE2_UFS_AXI_CLK>, + <&clock_gcc GCC_UFS_AHB_CLK>, + <&clock_gcc GCC_UFS_UNIPRO_CORE_CLK>, + <&clock_gcc GCC_UFS_ICE_CORE_CLK>, + <&clock_rpmcc RPM_LN_BB_CLK1>, + <&clock_gcc GCC_UFS_TX_SYMBOL_0_CLK>, + <&clock_gcc GCC_UFS_RX_SYMBOL_0_CLK>; + freq-table-hz = + <50000000 200000000>, + <0 0>, + <0 0>, + <37500000 150000000>, + <75000000 300000000>, + <0 0>, + <0 0>, + <0 0>; + + lanes-per-direction = <1>; + + qcom,msm-bus,name = "ufs1"; + qcom,msm-bus,num-cases = <12>; + qcom,msm-bus,num-paths = <2>; + qcom,msm-bus,vectors-KBps = + <95 512 0 0>, <1 650 0 0>, /* No vote */ + <95 512 922 0>, <1 650 1000 0>, /* PWM G1 */ + <95 512 1844 0>, <1 650 1000 0>, /* PWM G2 */ + <95 512 3688 0>, <1 650 1000 0>, /* PWM G3 */ + <95 512 7376 0>, <1 650 1000 0>, /* PWM G4 */ + <95 512 127796 0>, <1 650 1000 0>, /* HS G1 RA */ + <95 512 255591 0>, <1 650 1000 0>, /* HS G2 RA */ + <95 512 2097152 0>, <1 650 102400 0>, /* HS G3 RA */ + <95 512 149422 0>, <1 650 1000 0>, /* HS G1 RB */ + <95 512 298189 0>, <1 650 1000 0>, /* HS G2 RB */ + <95 512 2097152 0>, <1 650 102400 0>, /* HS G3 RB */ + <95 512 7643136 0>, <1 650 307200 0>; /* Max. bandwidth */ + qcom,bus-vector-names = "MIN", + "PWM_G1_L1", "PWM_G2_L1", "PWM_G3_L1", "PWM_G4_L1", + "HS_RA_G1_L1", "HS_RA_G2_L1", "HS_RA_G3_L1", + "HS_RB_G1_L1", "HS_RB_G2_L1", "HS_RB_G3_L1", + "MAX"; + + qcom,pm-qos-cpu-groups = <0x0F 0xF0>; + qcom,pm-qos-cpu-group-latency-us = <26 26>; + qcom,pm-qos-default-cpu = <0>; + + resets = <&clock_gcc GCC_UFS_BCR>; + reset-names = "core_reset"; + + status = "disabled"; + }; + usb3: ssusb@a800000 { compatible = "qcom,dwc-usb3-msm"; reg = <0x0a800000 0xfc100>, diff --git a/arch/arm/boot/dts/qcom/sdm660-gpu.dtsi b/arch/arm/boot/dts/qcom/sdm660-gpu.dtsi index 2adc4cfae77f..dedc0c99d2e5 100644 --- a/arch/arm/boot/dts/qcom/sdm660-gpu.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-gpu.dtsi @@ -58,8 +58,9 @@ label = "kgsl-3d0"; compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d"; status = "ok"; - reg = <0x5000000 0x40000>; - reg-names = "kgsl_3d0_reg_memory"; + reg = <0x5000000 0x40000 + 0x780000 0x6220>; + reg-names = "kgsl_3d0_reg_memory", "qfprom_memory"; interrupts = <0 300 0>; interrupt-names = "kgsl_3d0_irq"; qcom,id = <0>; @@ -135,6 +136,8 @@ /* Context aware jump target power level */ qcom,ca-target-pwrlevel = <4>; + qcom,gpu-speed-bin = <0x41a0 0x1fe00000 21>; + /* GPU Mempools */ qcom,gpu-mempools { #address-cells= <1>; @@ -155,92 +158,349 @@ }; }; - /* Power levels */ - qcom,gpu-pwrlevels { + /* + * Speed-bin zero is default speed bin. + * For rest of the speed bins, speed-bin value + * is calulated as FMAX/4.8 MHz round up to zero + * decimal places. + */ + qcom,gpu-pwrlevel-bins { #address-cells = <1>; #size-cells = <0>; - compatible = "qcom,gpu-pwrlevels"; - - /* TURBO */ - qcom,gpu-pwrlevel@0 { - reg = <0>; - qcom,gpu-freq = <750000000>; - qcom,bus-freq = <13>; - qcom,bus-min = <12>; - qcom,bus-max = <13>; - }; - - /* TURBO */ - qcom,gpu-pwrlevel@1 { - reg = <1>; - qcom,gpu-freq = <700000000>; - qcom,bus-freq = <11>; - qcom,bus-min = <11>; - qcom,bus-max = <13>; - }; - - /* NOM_L1 */ - qcom,gpu-pwrlevel@2 { - reg = <2>; - qcom,gpu-freq = <647000000>; - qcom,bus-freq = <11>; - qcom,bus-min = <10>; - qcom,bus-max = <12>; - }; - - /* NOM */ - qcom,gpu-pwrlevel@3 { - reg = <3>; - qcom,gpu-freq = <588000000>; - qcom,bus-freq = <10>; - qcom,bus-min = <9>; - qcom,bus-max = <12>; - }; - - /* SVS_L1 */ - qcom,gpu-pwrlevel@4 { - reg = <4>; - qcom,gpu-freq = <465000000>; - qcom,bus-freq = <9>; - qcom,bus-min = <8>; - qcom,bus-max = <11>; - }; - - /* SVS */ - qcom,gpu-pwrlevel@5 { - reg = <5>; - qcom,gpu-freq = <370000000>; - qcom,bus-freq = <8>; - qcom,bus-min = <6>; - qcom,bus-max = <9>; + compatible="qcom,gpu-pwrlevel-bins"; + + qcom,gpu-pwrlevels-0 { + #address-cells = <1>; + #size-cells = <0>; + + qcom,speed-bin = <0>; + + qcom,initial-pwrlevel = <6>; + + /* TURBO */ + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <750000000>; + qcom,bus-freq = <13>; + qcom,bus-min = <12>; + qcom,bus-max = <13>; + }; + + /* TURBO */ + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <700000000>; + qcom,bus-freq = <11>; + qcom,bus-min = <11>; + qcom,bus-max = <13>; + }; + + /* NOM_L1 */ + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <647000000>; + qcom,bus-freq = <11>; + qcom,bus-min = <10>; + qcom,bus-max = <12>; + }; + + /* NOM */ + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <588000000>; + qcom,bus-freq = <10>; + qcom,bus-min = <9>; + qcom,bus-max = <12>; + }; + + /* SVS_L1 */ + qcom,gpu-pwrlevel@4 { + reg = <4>; + qcom,gpu-freq = <465000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <8>; + qcom,bus-max = <11>; + }; + + /* SVS */ + qcom,gpu-pwrlevel@5 { + reg = <5>; + qcom,gpu-freq = <370000000>; + qcom,bus-freq = <8>; + qcom,bus-min = <6>; + qcom,bus-max = <9>; + }; + + /* Low SVS */ + qcom,gpu-pwrlevel@6 { + reg = <6>; + qcom,gpu-freq = <266000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <3>; + qcom,bus-max = <6>; + }; + + /* Min SVS */ + qcom,gpu-pwrlevel@7 { + reg = <7>; + qcom,gpu-freq = <160000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <3>; + qcom,bus-max = <5>; + }; + + /* XO */ + qcom,gpu-pwrlevel@8 { + reg = <8>; + qcom,gpu-freq = <19200000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; }; - /* Low SVS */ - qcom,gpu-pwrlevel@6 { - reg = <6>; - qcom,gpu-freq = <266000000>; - qcom,bus-freq = <3>; - qcom,bus-min = <3>; - qcom,bus-max = <6>; + qcom,gpu-pwrlevels-1 { + #address-cells = <1>; + #size-cells = <0>; + + qcom,speed-bin = <157>; + + qcom,initial-pwrlevel = <6>; + + /* TURBO */ + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <750000000>; + qcom,bus-freq = <13>; + qcom,bus-min = <12>; + qcom,bus-max = <13>; + }; + + /* TURBO */ + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <700000000>; + qcom,bus-freq = <11>; + qcom,bus-min = <11>; + qcom,bus-max = <13>; + }; + + /* NOM_L1 */ + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <647000000>; + qcom,bus-freq = <11>; + qcom,bus-min = <10>; + qcom,bus-max = <12>; + }; + + /* NOM */ + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <588000000>; + qcom,bus-freq = <10>; + qcom,bus-min = <9>; + qcom,bus-max = <12>; + }; + + /* SVS_L1 */ + qcom,gpu-pwrlevel@4 { + reg = <4>; + qcom,gpu-freq = <465000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <8>; + qcom,bus-max = <11>; + }; + + /* SVS */ + qcom,gpu-pwrlevel@5 { + reg = <5>; + qcom,gpu-freq = <370000000>; + qcom,bus-freq = <8>; + qcom,bus-min = <6>; + qcom,bus-max = <9>; + }; + + /* Low SVS */ + qcom,gpu-pwrlevel@6 { + reg = <6>; + qcom,gpu-freq = <266000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <3>; + qcom,bus-max = <6>; + }; + + /* Min SVS */ + qcom,gpu-pwrlevel@7 { + reg = <7>; + qcom,gpu-freq = <160000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <3>; + qcom,bus-max = <5>; + }; + + /* XO */ + qcom,gpu-pwrlevel@8 { + reg = <8>; + qcom,gpu-freq = <19200000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; }; - /* Min SVS */ - qcom,gpu-pwrlevel@7 { - reg = <7>; - qcom,gpu-freq = <160000000>; - qcom,bus-freq = <3>; - qcom,bus-min = <3>; - qcom,bus-max = <5>; + qcom,gpu-pwrlevels-2 { + #address-cells = <1>; + #size-cells = <0>; + + qcom,speed-bin = <146>; + + qcom,initial-pwrlevel = <5>; + + /* TURBO */ + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <700000000>; + qcom,bus-freq = <13>; + qcom,bus-min = <12>; + qcom,bus-max = <13>; + }; + + /* NOM_L1 */ + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <647000000>; + qcom,bus-freq = <11>; + qcom,bus-min = <10>; + qcom,bus-max = <12>; + }; + + /* NOM */ + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <588000000>; + qcom,bus-freq = <10>; + qcom,bus-min = <9>; + qcom,bus-max = <12>; + }; + + /* SVS_L1 */ + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <465000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <8>; + qcom,bus-max = <11>; + }; + + /* SVS */ + qcom,gpu-pwrlevel@4 { + reg = <4>; + qcom,gpu-freq = <370000000>; + qcom,bus-freq = <8>; + qcom,bus-min = <6>; + qcom,bus-max = <9>; + }; + + /* Low SVS */ + qcom,gpu-pwrlevel@5 { + reg = <5>; + qcom,gpu-freq = <266000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <3>; + qcom,bus-max = <6>; + }; + + /* Min SVS */ + qcom,gpu-pwrlevel@6 { + reg = <6>; + qcom,gpu-freq = <160000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <3>; + qcom,bus-max = <5>; + }; + + /* XO */ + qcom,gpu-pwrlevel@7 { + reg = <7>; + qcom,gpu-freq = <19200000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; }; - /* XO */ - qcom,gpu-pwrlevel@8 { - reg = <8>; - qcom,gpu-freq = <19200000>; - qcom,bus-freq = <0>; - qcom,bus-min = <0>; - qcom,bus-max = <0>; + qcom,gpu-pwrlevels-3 { + #address-cells = <1>; + #size-cells = <0>; + + qcom,speed-bin = <135>; + + qcom,initial-pwrlevel = <4>; + + /* NOM_L1 */ + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <647000000>; + qcom,bus-freq = <13>; + qcom,bus-min = <12>; + qcom,bus-max = <13>; + }; + + /* NOM */ + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <588000000>; + qcom,bus-freq = <10>; + qcom,bus-min = <9>; + qcom,bus-max = <12>; + }; + + /* SVS_L1 */ + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <465000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <8>; + qcom,bus-max = <11>; + }; + + /* SVS */ + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <370000000>; + qcom,bus-freq = <8>; + qcom,bus-min = <6>; + qcom,bus-max = <9>; + }; + + /* Low SVS */ + qcom,gpu-pwrlevel@4 { + reg = <4>; + qcom,gpu-freq = <266000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <3>; + qcom,bus-max = <6>; + }; + + /* Min SVS */ + qcom,gpu-pwrlevel@5 { + reg = <5>; + qcom,gpu-freq = <160000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <3>; + qcom,bus-max = <5>; + }; + + /* XO */ + qcom,gpu-pwrlevel@6 { + reg = <6>; + qcom,gpu-freq = <19200000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; }; }; }; diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 3c8c1f9acbfa..fd0123d79f1d 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -1493,6 +1493,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, return err; } +static int fastrpc_channel_open(struct fastrpc_file *fl); static int fastrpc_init_process(struct fastrpc_file *fl, struct fastrpc_ioctl_init_attrs *uproc) { @@ -1501,6 +1502,10 @@ static int fastrpc_init_process(struct fastrpc_file *fl, struct fastrpc_ioctl_init *init = &uproc->init; struct smq_phy_page pages[1]; struct fastrpc_mmap *file = 0, *mem = 0; + + VERIFY(err, !fastrpc_channel_open(fl)); + if (err) + goto bail; if (init->flags == FASTRPC_INIT_ATTACH) { remote_arg_t ra[1]; int tgid = current->tgid; @@ -1651,6 +1656,9 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl) remote_arg_t ra[1]; int tgid = 0; + VERIFY(err, fl->cid >= 0 && fl->cid < NUM_CHANNELS); + if (err) + goto bail; VERIFY(err, fl->apps->channel[fl->cid].chan != 0); if (err) goto bail; @@ -2307,42 +2315,20 @@ static const struct file_operations debugfs_fops = { .open = fastrpc_debugfs_open, .read = fastrpc_debugfs_read, }; - -static int fastrpc_device_open(struct inode *inode, struct file *filp) +static int fastrpc_channel_open(struct fastrpc_file *fl) { - int cid = MINOR(inode->i_rdev); - struct dentry *debugfs_file; - int err = 0; struct fastrpc_apps *me = &gfa; - struct fastrpc_file *fl = 0; - - VERIFY(err, fl = kzalloc(sizeof(*fl), GFP_KERNEL)); - if (err) - return err; - - filp->private_data = fl; + int cid, err = 0; mutex_lock(&me->smd_mutex); - debugfs_file = debugfs_create_file(current->comm, 0644, debugfs_root, - fl, &debugfs_fops); - context_list_ctor(&fl->clst); - spin_lock_init(&fl->hlock); - INIT_HLIST_HEAD(&fl->maps); - INIT_HLIST_HEAD(&fl->bufs); - INIT_HLIST_NODE(&fl->hn); - fl->tgid = current->tgid; - fl->apps = me; - fl->cid = cid; - if (debugfs_file != NULL) - fl->debugfs_file = debugfs_file; - memset(&fl->perf, 0, sizeof(fl->perf)); - - VERIFY(err, !fastrpc_session_alloc_locked(&me->channel[cid], 0, - &fl->sctx)); + VERIFY(err, fl && fl->sctx); + if (err) + goto bail; + cid = fl->cid; + VERIFY(err, cid >= 0 && cid < NUM_CHANNELS); if (err) goto bail; - fl->cid = cid; fl->ssrcount = me->channel[cid].ssrcount; if ((kref_get_unless_zero(&me->channel[cid].kref) == 0) || (me->channel[cid].chan == 0)) { @@ -2368,25 +2354,58 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) me->channel[cid].ssrcount; } } - spin_lock(&me->hlock); - hlist_add_head(&fl->hn, &me->drivers); - spin_unlock(&me->hlock); bail: mutex_unlock(&me->smd_mutex); - - if (err && fl) - fastrpc_device_release(inode, filp); return err; } +static int fastrpc_device_open(struct inode *inode, struct file *filp) +{ + int err = 0; + struct fastrpc_file *fl = 0; + struct fastrpc_apps *me = &gfa; + + VERIFY(err, fl = kzalloc(sizeof(*fl), GFP_KERNEL)); + if (err) + return err; + + context_list_ctor(&fl->clst); + spin_lock_init(&fl->hlock); + INIT_HLIST_HEAD(&fl->maps); + INIT_HLIST_HEAD(&fl->bufs); + INIT_HLIST_NODE(&fl->hn); + fl->tgid = current->tgid; + fl->apps = me; + fl->mode = FASTRPC_MODE_SERIAL; + fl->cid = -1; + filp->private_data = fl; + spin_lock(&me->hlock); + hlist_add_head(&fl->hn, &me->drivers); + spin_unlock(&me->hlock); + return 0; +} + static int fastrpc_get_info(struct fastrpc_file *fl, uint32_t *info) { int err = 0; + uint32_t cid; - VERIFY(err, fl && fl->sctx); + VERIFY(err, fl != 0); if (err) goto bail; + if (fl->cid == -1) { + cid = *info; + VERIFY(err, cid < NUM_CHANNELS); + if (err) + goto bail; + fl->cid = cid; + fl->ssrcount = fl->apps->channel[cid].ssrcount; + VERIFY(err, !fastrpc_session_alloc_locked( + &fl->apps->channel[cid], 0, &fl->sctx)); + if (err) + goto bail; + } *info = (fl->sctx->smmu.enabled ? 1 : 0); bail: return err; @@ -2487,6 +2506,9 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, goto bail; break; case FASTRPC_IOCTL_GETINFO: + VERIFY(err, 0 == copy_from_user(&info, param, sizeof(info))); + if (err) + goto bail; VERIFY(err, 0 == (err = fastrpc_get_info(fl, &info))); if (err) goto bail; @@ -2802,6 +2824,7 @@ static struct platform_driver fastrpc_driver = { static int __init fastrpc_device_init(void) { struct fastrpc_apps *me = &gfa; + struct device *dev = 0; int err = 0, i; memset(me, 0, sizeof(*me)); @@ -2818,7 +2841,7 @@ static int __init fastrpc_device_init(void) cdev_init(&me->cdev, &fops); me->cdev.owner = THIS_MODULE; VERIFY(err, 0 == cdev_add(&me->cdev, MKDEV(MAJOR(me->dev_no), 0), - NUM_CHANNELS)); + 1)); if (err) goto cdev_init_bail; me->class = class_create(THIS_MODULE, "fastrpc"); @@ -2826,15 +2849,14 @@ static int __init fastrpc_device_init(void) if (err) goto class_create_bail; me->compat = (NULL == fops.compat_ioctl) ? 0 : 1; + dev = device_create(me->class, NULL, + MKDEV(MAJOR(me->dev_no), 0), + NULL, gcinfo[0].name); + VERIFY(err, !IS_ERR_OR_NULL(dev)); + if (err) + goto device_create_bail; for (i = 0; i < NUM_CHANNELS; i++) { - if (!gcinfo[i].name) - continue; - me->channel[i].dev = device_create(me->class, NULL, - MKDEV(MAJOR(me->dev_no), i), - NULL, gcinfo[i].name); - VERIFY(err, !IS_ERR(me->channel[i].dev)); - if (err) - goto device_create_bail; + me->channel[i].dev = dev; me->channel[i].ssrcount = 0; me->channel[i].prevssrcount = 0; me->channel[i].ramdumpenabled = 0; @@ -2853,12 +2875,12 @@ static int __init fastrpc_device_init(void) return 0; device_create_bail: for (i = 0; i < NUM_CHANNELS; i++) { - if (IS_ERR_OR_NULL(me->channel[i].dev)) - continue; - device_destroy(me->class, MKDEV(MAJOR(me->dev_no), i)); - subsys_notif_unregister_notifier(me->channel[i].handle, - &me->channel[i].nb); + if (me->channel[i].handle) + subsys_notif_unregister_notifier(me->channel[i].handle, + &me->channel[i].nb); } + if (!IS_ERR_OR_NULL(dev)) + device_destroy(me->class, MKDEV(MAJOR(me->dev_no), 0)); class_destroy(me->class); class_create_bail: cdev_del(&me->cdev); diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c index f7e84dd55606..fcd6d1142618 100644 --- a/drivers/char/adsprpc_compat.c +++ b/drivers/char/adsprpc_compat.c @@ -391,6 +391,10 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, sizeof(*info)))); if (err) return -EFAULT; + err = get_user(u, info32); + err |= put_user(u, info); + if (err) + return err; ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_GETINFO, (unsigned long)info); if (ret) diff --git a/drivers/crypto/msm/ota_crypto.c b/drivers/crypto/msm/ota_crypto.c index 9b4a001bec95..674913cb20bf 100644 --- a/drivers/crypto/msm/ota_crypto.c +++ b/drivers/crypto/msm/ota_crypto.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2014,2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -880,8 +880,8 @@ static ssize_t _debug_stats_read(struct file *file, char __user *buf, int len; len = _disp_stats(); - - rc = simple_read_from_buffer((void __user *) buf, len, + if (len <= count) + rc = simple_read_from_buffer((void __user *) buf, len, ppos, (void *) _debug_read_buf, len); return rc; diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c index a629c621648c..5ce87a6edcc3 100644 --- a/drivers/crypto/msm/qcedev.c +++ b/drivers/crypto/msm/qcedev.c @@ -1987,9 +1987,9 @@ static ssize_t _debug_stats_read(struct file *file, char __user *buf, len = _disp_stats(qcedev); - rc = simple_read_from_buffer((void __user *) buf, len, + if (len <= count) + rc = simple_read_from_buffer((void __user *) buf, len, ppos, (void *) _debug_read_buf, len); - return rc; } diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c index a898dbcbd0ca..893b0b6da6b8 100644 --- a/drivers/crypto/msm/qcrypto.c +++ b/drivers/crypto/msm/qcrypto.c @@ -1,6 +1,6 @@ /* Qualcomm Crypto driver * - * Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -5419,9 +5419,9 @@ static ssize_t _debug_stats_read(struct file *file, char __user *buf, len = _disp_stats(qcrypto); - rc = simple_read_from_buffer((void __user *) buf, len, + if (len <= count) + rc = simple_read_from_buffer((void __user *) buf, len, ppos, (void *) _debug_read_buf, len); - return rc; } diff --git a/drivers/iio/adc/qcom-rradc.c b/drivers/iio/adc/qcom-rradc.c index b7504fdd380f..57145ea72e90 100644 --- a/drivers/iio/adc/qcom-rradc.c +++ b/drivers/iio/adc/qcom-rradc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -165,10 +165,19 @@ #define FAB_ID_GF 0x30 #define FAB_ID_SMIC 0x11 +#define FAB_ID_660_GF 0x0 +#define FAB_ID_660_TSMC 0x2 +#define FAB_ID_660_MX 0x3 #define FG_ADC_RR_CHG_TEMP_GF_OFFSET_UV 1303168 #define FG_ADC_RR_CHG_TEMP_GF_SLOPE_UV_PER_C 3784 #define FG_ADC_RR_CHG_TEMP_SMIC_OFFSET_UV 1338433 #define FG_ADC_RR_CHG_TEMP_SMIC_SLOPE_UV_PER_C 3655 +#define FG_ADC_RR_CHG_TEMP_660_GF_OFFSET_UV 1309001 +#define FG_RR_CHG_TEMP_660_GF_SLOPE_UV_PER_C 3403 +#define FG_ADC_RR_CHG_TEMP_660_SMIC_OFFSET_UV 1295898 +#define FG_RR_CHG_TEMP_660_SMIC_SLOPE_UV_PER_C 3596 +#define FG_ADC_RR_CHG_TEMP_660_MGNA_OFFSET_UV 1314779 +#define FG_RR_CHG_TEMP_660_MGNA_SLOPE_UV_PER_C 3496 #define FG_ADC_RR_CHG_TEMP_OFFSET_MILLI_DEGC 25000 #define FG_ADC_RR_CHG_THRESHOLD_SCALE 4 @@ -388,23 +397,70 @@ static int rradc_post_process_die_temp(struct rradc_chip *chip, return 0; } +static int rradc_get_660_fab_coeff(struct rradc_chip *chip, + int64_t *offset, int64_t *slope) +{ + switch (chip->pmic_fab_id->fab_id) { + case FAB_ID_660_GF: + *offset = FG_ADC_RR_CHG_TEMP_660_GF_OFFSET_UV; + *slope = FG_RR_CHG_TEMP_660_GF_SLOPE_UV_PER_C; + break; + case FAB_ID_660_TSMC: + *offset = FG_ADC_RR_CHG_TEMP_660_SMIC_OFFSET_UV; + *slope = FG_RR_CHG_TEMP_660_SMIC_SLOPE_UV_PER_C; + break; + default: + *offset = FG_ADC_RR_CHG_TEMP_660_MGNA_OFFSET_UV; + *slope = FG_RR_CHG_TEMP_660_MGNA_SLOPE_UV_PER_C; + } + + return 0; +} + +static int rradc_get_8998_fab_coeff(struct rradc_chip *chip, + int64_t *offset, int64_t *slope) +{ + switch (chip->pmic_fab_id->fab_id) { + case FAB_ID_GF: + *offset = FG_ADC_RR_CHG_TEMP_GF_OFFSET_UV; + *slope = FG_ADC_RR_CHG_TEMP_GF_SLOPE_UV_PER_C; + break; + case FAB_ID_SMIC: + *offset = FG_ADC_RR_CHG_TEMP_SMIC_OFFSET_UV; + *slope = FG_ADC_RR_CHG_TEMP_SMIC_SLOPE_UV_PER_C; + break; + default: + return -EINVAL; + } + + return 0; +} + static int rradc_post_process_chg_temp_hot(struct rradc_chip *chip, struct rradc_chan_prop *prop, u16 adc_code, int *result_millidegc) { int64_t uv = 0, offset = 0, slope = 0; + int rc = 0; if (chip->revid_dev_node) { - switch (chip->pmic_fab_id->fab_id) { - case FAB_ID_GF: - offset = FG_ADC_RR_CHG_TEMP_GF_OFFSET_UV; - slope = FG_ADC_RR_CHG_TEMP_GF_SLOPE_UV_PER_C; + switch (chip->pmic_fab_id->pmic_subtype) { + case PM660_SUBTYPE: + rc = rradc_get_660_fab_coeff(chip, &offset, &slope); + if (rc < 0) { + pr_err("Unable to get fab id coefficients\n"); + return -EINVAL; + } break; - case FAB_ID_SMIC: - offset = FG_ADC_RR_CHG_TEMP_SMIC_OFFSET_UV; - slope = FG_ADC_RR_CHG_TEMP_SMIC_SLOPE_UV_PER_C; + case PMI8998_SUBTYPE: + rc = rradc_get_8998_fab_coeff(chip, &offset, &slope); + if (rc < 0) { + pr_err("Unable to get fab id coefficients\n"); + return -EINVAL; + } break; default: + pr_err("No PMIC subtype found\n"); return -EINVAL; } } else { @@ -444,18 +500,26 @@ static int rradc_post_process_chg_temp(struct rradc_chip *chip, int *result_millidegc) { int64_t uv = 0, offset = 0, slope = 0; + int rc = 0; if (chip->revid_dev_node) { - switch (chip->pmic_fab_id->fab_id) { - case FAB_ID_GF: - offset = FG_ADC_RR_CHG_TEMP_GF_OFFSET_UV; - slope = FG_ADC_RR_CHG_TEMP_GF_SLOPE_UV_PER_C; + switch (chip->pmic_fab_id->pmic_subtype) { + case PM660_SUBTYPE: + rc = rradc_get_660_fab_coeff(chip, &offset, &slope); + if (rc < 0) { + pr_err("Unable to get fab id coefficients\n"); + return -EINVAL; + } break; - case FAB_ID_SMIC: - offset = FG_ADC_RR_CHG_TEMP_SMIC_OFFSET_UV; - slope = FG_ADC_RR_CHG_TEMP_SMIC_SLOPE_UV_PER_C; + case PMI8998_SUBTYPE: + rc = rradc_get_8998_fab_coeff(chip, &offset, &slope); + if (rc < 0) { + pr_err("Unable to get fab id coefficients\n"); + return -EINVAL; + } break; default: + pr_err("No PMIC subtype found\n"); return -EINVAL; } } else { 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 dd7d1c836809..1ddf51407884 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 @@ -846,6 +846,7 @@ void msm_isp_increment_frame_id(struct vfe_device *vfe_dev, enum msm_vfe_dual_hw_type dual_hw_type; enum msm_vfe_dual_hw_ms_type ms_type; unsigned long flags; + int i; struct master_slave_resource_info *ms_res = &vfe_dev->common_data->ms_resource; @@ -869,8 +870,27 @@ void msm_isp_increment_frame_id(struct vfe_device *vfe_dev, src_info->dual_hw_ms_info.index)) { pr_err("Frame out of sync on vfe %d\n", vfe_dev->pdev->id); - msm_isp_halt_send_error(vfe_dev, - ISP_EVENT_BUF_FATAL_ERROR); + /* + * set this isp as async mode to force + *it sync again at the next sof + */ + src_info->dual_hw_ms_info.sync_state = + MSM_ISP_DUAL_CAM_ASYNC; + /* + * set the other isp as async mode to force + * it sync again at the next sof + */ + for (i = 0; i < MAX_VFE * VFE_SRC_MAX; i++) { + if (ms_res->src_info[i] == NULL) + continue; + if (src_info == ms_res->src_info[i] || + ms_res->src_info[i]-> + active == 0) + continue; + ms_res->src_info[i]->dual_hw_ms_info. + sync_state = + MSM_ISP_DUAL_CAM_ASYNC; + } } ms_res->src_sof_mask |= (1 << src_info->dual_hw_ms_info.index); diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c index e3022b2dbe34..55a743737c59 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c +++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -58,6 +58,7 @@ #define TRUE 1 #define FALSE 0 +#define MAX_LANE_COUNT 4 #define CSID_TIMEOUT msecs_to_jiffies(100) #undef CDBG @@ -284,6 +285,12 @@ static int msm_csid_config(struct csid_device *csid_dev, csid_params->lane_assign); CDBG("%s csid_params phy_sel = %d\n", __func__, csid_params->phy_sel); + if ((csid_params->lane_cnt == 0) || + (csid_params->lane_cnt > MAX_LANE_COUNT)) { + pr_err("%s:%d invalid lane count = %d\n", + __func__, __LINE__, csid_params->lane_cnt); + return -EINVAL; + } csid_dev->csid_lane_cnt = csid_params->lane_cnt; rc = msm_csid_reset(csid_dev); diff --git a/drivers/net/ethernet/msm/ecm_ipa.c b/drivers/net/ethernet/msm/ecm_ipa.c index c7c4da22139d..0f25932d8855 100644 --- a/drivers/net/ethernet/msm/ecm_ipa.c +++ b/drivers/net/ethernet/msm/ecm_ipa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -9,7 +9,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ - #include <linux/debugfs.h> #include <linux/errno.h> #include <linux/etherdevice.h> @@ -106,10 +105,6 @@ enum ecm_ipa_operation { * struct ecm_ipa_dev - main driver context parameters * @net: network interface struct implemented by this driver * @directory: debugfs directory for various debuging switches - * @tx_enable: flag that enable/disable Tx path to continue to IPA - * @rx_enable: flag that enable/disable Rx path to continue to IPA - * @rm_enable: flag that enable/disable Resource manager request prior to Tx - * @dma_enable: flag that allow on-the-fly DMA mode for IPA * @eth_ipv4_hdr_hdl: saved handle for ipv4 header-insertion table * @eth_ipv6_hdr_hdl: saved handle for ipv6 header-insertion table * @usb_to_ipa_hdl: save handle for IPA pipe operations @@ -129,10 +124,6 @@ enum ecm_ipa_operation { */ struct ecm_ipa_dev { struct net_device *net; - u32 tx_enable; - u32 rx_enable; - u32 rm_enable; - bool dma_enable; struct dentry *directory; uint32_t eth_ipv4_hdr_hdl; uint32_t eth_ipv6_hdr_hdl; @@ -167,32 +158,16 @@ static void ecm_ipa_rm_notify(void *user_data, enum ipa_rm_event event, static struct net_device_stats *ecm_ipa_get_stats(struct net_device *net); static int ecm_ipa_create_rm_resource(struct ecm_ipa_dev *ecm_ipa_ctx); static void ecm_ipa_destory_rm_resource(struct ecm_ipa_dev *ecm_ipa_ctx); -static bool rx_filter(struct sk_buff *skb); -static bool tx_filter(struct sk_buff *skb); -static bool rm_enabled(struct ecm_ipa_dev *ecm_ipa_ctx); static int resource_request(struct ecm_ipa_dev *ecm_ipa_ctx); static void resource_release(struct ecm_ipa_dev *ecm_ipa_ctx); static netdev_tx_t ecm_ipa_start_xmit(struct sk_buff *skb, struct net_device *net); -static int ecm_ipa_debugfs_stall_open(struct inode *inode, - struct file *file); -static ssize_t ecm_ipa_debugfs_stall_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos); static int ecm_ipa_debugfs_atomic_open(struct inode *inode, struct file *file); -static ssize_t ecm_ipa_debugfs_enable_write_dma(struct file *file, - const char __user *buf, size_t count, loff_t *ppos); -static int ecm_ipa_debugfs_dma_open(struct inode *inode, struct file *file); -static ssize_t ecm_ipa_debugfs_enable_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos); -static ssize_t ecm_ipa_debugfs_enable_read(struct file *file, - char __user *ubuf, size_t count, loff_t *ppos); static ssize_t ecm_ipa_debugfs_atomic_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos); static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *ecm_ipa_ctx); static void ecm_ipa_debugfs_destroy(struct ecm_ipa_dev *ecm_ipa_ctx); static int ecm_ipa_ep_registers_cfg(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl); -static int ecm_ipa_ep_registers_dma_cfg(u32 usb_to_ipa_hdl, - enum ipa_client_type prod_client); static int ecm_ipa_set_device_ethernet_addr(u8 *dev_ethaddr, u8 device_ethaddr[]); static enum ecm_ipa_state ecm_ipa_next_state(enum ecm_ipa_state current_state, @@ -210,22 +185,11 @@ static const struct net_device_ops ecm_ipa_netdev_ops = { .ndo_get_stats = ecm_ipa_get_stats, }; -const struct file_operations ecm_ipa_debugfs_dma_ops = { - .open = ecm_ipa_debugfs_dma_open, - .read = ecm_ipa_debugfs_enable_read, - .write = ecm_ipa_debugfs_enable_write_dma, -}; - const struct file_operations ecm_ipa_debugfs_atomic_ops = { .open = ecm_ipa_debugfs_atomic_open, .read = ecm_ipa_debugfs_atomic_read, }; -const struct file_operations ecm_ipa_debugfs_stall_ops = { - .open = ecm_ipa_debugfs_stall_open, - .write = ecm_ipa_debugfs_stall_write, -}; - static void ecm_ipa_msg_free_cb(void *buff, u32 len, u32 type) { kfree(buff); @@ -286,9 +250,6 @@ int ecm_ipa_init(struct ecm_ipa_params *params) ECM_IPA_DEBUG("ecm_ipa_ctx (private) = %p\n", ecm_ipa_ctx); ecm_ipa_ctx->net = net; - ecm_ipa_ctx->tx_enable = true; - ecm_ipa_ctx->rx_enable = true; - ecm_ipa_ctx->rm_enable = true; ecm_ipa_ctx->outstanding_high = DEFAULT_OUTSTANDING_HIGH; ecm_ipa_ctx->outstanding_low = DEFAULT_OUTSTANDING_LOW; atomic_set(&ecm_ipa_ctx->outstanding_pkts, 0); @@ -604,12 +565,6 @@ static netdev_tx_t ecm_ipa_start_xmit(struct sk_buff *skb, return NETDEV_TX_BUSY; } - if (unlikely(tx_filter(skb))) { - dev_kfree_skb_any(skb); - ECM_IPA_DEBUG("packet got filtered out on Tx path\n"); - status = NETDEV_TX_OK; - goto out; - } ret = resource_request(ecm_ipa_ctx); if (ret) { ECM_IPA_DEBUG("Waiting to resource\n"); @@ -683,11 +638,6 @@ static void ecm_ipa_packet_receive_notify(void *priv, skb->dev = ecm_ipa_ctx->net; skb->protocol = eth_type_trans(skb, ecm_ipa_ctx->net); - if (rx_filter(skb)) { - ECM_IPA_DEBUG("packet got filtered out on Rx path\n"); - dev_kfree_skb_any(skb); - return; - } result = netif_rx(skb); if (result) @@ -1150,42 +1100,15 @@ static void ecm_ipa_destory_rm_resource(struct ecm_ipa_dev *ecm_ipa_ctx) ECM_IPA_LOG_EXIT(); } -static bool rx_filter(struct sk_buff *skb) -{ - struct ecm_ipa_dev *ecm_ipa_ctx = netdev_priv(skb->dev); - return !ecm_ipa_ctx->rx_enable; -} - -static bool tx_filter(struct sk_buff *skb) -{ - struct ecm_ipa_dev *ecm_ipa_ctx = netdev_priv(skb->dev); - return !ecm_ipa_ctx->tx_enable; -} - -static bool rm_enabled(struct ecm_ipa_dev *ecm_ipa_ctx) -{ - return ecm_ipa_ctx->rm_enable; -} - static int resource_request(struct ecm_ipa_dev *ecm_ipa_ctx) { - int result = 0; - - if (!rm_enabled(ecm_ipa_ctx)) - goto out; - result = ipa_rm_inactivity_timer_request_resource( - IPA_RM_RESOURCE_STD_ECM_PROD); -out: - return result; + return ipa_rm_inactivity_timer_request_resource( + IPA_RM_RESOURCE_STD_ECM_PROD); } static void resource_release(struct ecm_ipa_dev *ecm_ipa_ctx) { - if (!rm_enabled(ecm_ipa_ctx)) - goto out; ipa_rm_inactivity_timer_release_resource(IPA_RM_RESOURCE_STD_ECM_PROD); -out: - return; } /** @@ -1258,45 +1181,6 @@ static void ecm_ipa_tx_timeout(struct net_device *net) net->stats.tx_errors++; } -static int ecm_ipa_debugfs_stall_open(struct inode *inode, - struct file *file) -{ - ECM_IPA_LOG_ENTRY(); - - ECM_IPA_LOG_EXIT(); - - return 0; -} - -static ssize_t ecm_ipa_debugfs_stall_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - u32 cmdq_cfg_mmio_phy = 0xFD4E3038; - void *cmdq_cfg_mmio_virt; - int result; - bool val = 0; - - ECM_IPA_LOG_ENTRY(); - - file->private_data = &val; - result = ecm_ipa_debugfs_enable_write(file, buf, count, ppos); - - cmdq_cfg_mmio_virt = ioremap(cmdq_cfg_mmio_phy, sizeof(u32)); - if (!cmdq_cfg_mmio_virt) { - ECM_IPA_ERROR("fail on mmio for cmdq_cfg_mmio_phy=0x%x", - cmdq_cfg_mmio_phy); - return result; - } - - iowrite32(val, cmdq_cfg_mmio_virt); - ECM_IPA_DEBUG("Value %d was written to cfgq", val); - - ECM_IPA_LOG_EXIT(); - - return result; - -} - static int ecm_ipa_debugfs_atomic_open(struct inode *inode, struct file *file) { struct ecm_ipa_dev *ecm_ipa_ctx = inode->i_private; @@ -1306,78 +1190,6 @@ static int ecm_ipa_debugfs_atomic_open(struct inode *inode, struct file *file) return 0; } -static ssize_t ecm_ipa_debugfs_enable_write_dma(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - struct ecm_ipa_dev *ecm_ipa_ctx = file->private_data; - int result; - ECM_IPA_LOG_ENTRY(); - file->private_data = &ecm_ipa_ctx->dma_enable; - result = ecm_ipa_debugfs_enable_write(file, buf, count, ppos); - if (ecm_ipa_ctx->dma_enable) - ecm_ipa_ep_registers_dma_cfg(ecm_ipa_ctx->usb_to_ipa_hdl, - ecm_ipa_ctx->ipa_to_usb_client); - else - ecm_ipa_ep_registers_cfg(ecm_ipa_ctx->usb_to_ipa_hdl, - ecm_ipa_ctx->usb_to_ipa_hdl); - ECM_IPA_LOG_EXIT(); - return result; -} - -static int ecm_ipa_debugfs_dma_open(struct inode *inode, struct file *file) -{ - struct ecm_ipa_dev *ecm_ipa_ctx = inode->i_private; - ECM_IPA_LOG_ENTRY(); - file->private_data = ecm_ipa_ctx; - ECM_IPA_LOG_EXIT(); - return 0; -} - -static ssize_t ecm_ipa_debugfs_enable_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - unsigned long missing; - char input; - bool *enable = file->private_data; - if (count != sizeof(input) + 1) { - ECM_IPA_ERROR("wrong input length(%zd)\n", count); - return -EINVAL; - } - if (!buf) { - ECM_IPA_ERROR("Bad argument\n"); - return -EINVAL; - } - missing = copy_from_user(&input, buf, 1); - if (missing) - return -EFAULT; - ECM_IPA_DEBUG("input received %c\n", input); - *enable = input - '0'; - ECM_IPA_DEBUG("value was set to %d\n", *enable); - return count; -} - -static ssize_t ecm_ipa_debugfs_enable_read(struct file *file, - char __user *ubuf, size_t count, loff_t *ppos) -{ - int nbytes; - int size = 0; - int ret; - loff_t pos; - u8 enable_str[sizeof(char)*3] = {0}; - bool *enable = file->private_data; - pos = *ppos; - nbytes = scnprintf(enable_str, sizeof(enable_str), "%d\n", *enable); - ret = simple_read_from_buffer(ubuf, count, ppos, enable_str, nbytes); - if (ret < 0) { - ECM_IPA_ERROR("simple_read_from_buffer problem\n"); - return ret; - } - size += ret; - count -= nbytes; - *ppos = pos + size; - return size; -} - static ssize_t ecm_ipa_debugfs_atomic_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { @@ -1394,7 +1206,6 @@ static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *ecm_ipa_ctx) { const mode_t flags_read_write = S_IRUGO | S_IWUGO; const mode_t flags_read_only = S_IRUGO; - const mode_t flags_write_only = S_IWUGO; struct dentry *file; ECM_IPA_LOG_ENTRY(); @@ -1407,24 +1218,6 @@ static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *ecm_ipa_ctx) ECM_IPA_ERROR("could not create debugfs directory entry\n"); goto fail_directory; } - file = debugfs_create_bool("tx_enable", flags_read_write, - ecm_ipa_ctx->directory, &ecm_ipa_ctx->tx_enable); - if (!file) { - ECM_IPA_ERROR("could not create debugfs tx file\n"); - goto fail_file; - } - file = debugfs_create_bool("rx_enable", flags_read_write, - ecm_ipa_ctx->directory, &ecm_ipa_ctx->rx_enable); - if (!file) { - ECM_IPA_ERROR("could not create debugfs rx file\n"); - goto fail_file; - } - file = debugfs_create_bool("rm_enable", flags_read_write, - ecm_ipa_ctx->directory, &ecm_ipa_ctx->rm_enable); - if (!file) { - ECM_IPA_ERROR("could not create debugfs rm file\n"); - goto fail_file; - } file = debugfs_create_u8("outstanding_high", flags_read_write, ecm_ipa_ctx->directory, &ecm_ipa_ctx->outstanding_high); if (!file) { @@ -1437,13 +1230,6 @@ static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *ecm_ipa_ctx) ECM_IPA_ERROR("could not create outstanding_low file\n"); goto fail_file; } - file = debugfs_create_file("dma_enable", flags_read_write, - ecm_ipa_ctx->directory, - ecm_ipa_ctx, &ecm_ipa_debugfs_dma_ops); - if (!file) { - ECM_IPA_ERROR("could not create debugfs dma file\n"); - goto fail_file; - } file = debugfs_create_file("outstanding", flags_read_only, ecm_ipa_ctx->directory, ecm_ipa_ctx, &ecm_ipa_debugfs_atomic_ops); @@ -1452,14 +1238,7 @@ static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *ecm_ipa_ctx) goto fail_file; } - file = debugfs_create_file("stall_ipa_rx_proc", flags_write_only, - ecm_ipa_ctx->directory, - ecm_ipa_ctx, &ecm_ipa_debugfs_stall_ops); - if (!file) { - ECM_IPA_ERROR("could not create stall_ipa_rx_proc file\n"); - goto fail_file; - } - + ECM_IPA_DEBUG("debugfs entries were created\n"); ECM_IPA_LOG_EXIT(); return 0; @@ -1523,46 +1302,6 @@ out: } /** - * ecm_ipa_ep_registers_dma_cfg() - configure the USB endpoints for ECM - * DMA - * @usb_to_ipa_hdl: handle received from ipa_connect - * - * This function will override the previous configuration - * which is needed for cores that does not support blocks logic - * Note that client handles are the actual pipe index - */ -static int ecm_ipa_ep_registers_dma_cfg(u32 usb_to_ipa_hdl, - enum ipa_client_type prod_client) -{ - int result = 0; - struct ipa_ep_cfg_mode cfg_mode; - u32 apps_to_ipa_hdl = 2; - - ECM_IPA_LOG_ENTRY(); - - memset(&cfg_mode, 0 , sizeof(cfg_mode)); - cfg_mode.mode = IPA_DMA; - cfg_mode.dst = prod_client; - result = ipa_cfg_ep_mode(apps_to_ipa_hdl, &cfg_mode); - if (result) { - ECM_IPA_ERROR("failed to configure Apps to IPA\n"); - goto out; - } - memset(&cfg_mode, 0 , sizeof(cfg_mode)); - cfg_mode.mode = IPA_DMA; - cfg_mode.dst = IPA_CLIENT_A5_LAN_WAN_CONS; - result = ipa_cfg_ep_mode(usb_to_ipa_hdl, &cfg_mode); - if (result) { - ECM_IPA_ERROR("failed to configure USB to IPA\n"); - goto out; - } - ECM_IPA_DEBUG("end-point registers successfully configured\n"); -out: - ECM_IPA_LOG_EXIT(); - return result; -} - -/** * ecm_ipa_set_device_ethernet_addr() - set device etherenet address * @dev_ethaddr: device etherenet address * diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig index db1ca629cbd6..f0c831b4b3d9 100644 --- a/drivers/net/wireless/ath/ath10k/Kconfig +++ b/drivers/net/wireless/ath/ath10k/Kconfig @@ -21,6 +21,26 @@ config ATH10K_AHB ---help--- This module adds support for AHB bus +config ATH10K_TARGET_SNOC + tristate "Atheros ath10k SNOC support" + depends on ATH10K + ---help--- + This module adds support for the Integrated WCN3990 WLAN module, + WCN3990 has integrated 802.11ac chipset with SNOC bus interface. + This module also adds support to register the WCN3990 wlan module + with MAC80211 network subsystem. + +config ATH10K_SNOC + bool "Enable/disable Atheros ath10k SNOC bus interface support" + depends on ATH10K + depends on ATH10K_TARGET_SNOC + ---help--- + This module add support for WLAN SNOC bus registration, WLAN + copy engine configuration for the WCN3990 chipset, WLAN hardware + shadow register configuration, create host to target communication + interface to interact with WLAN firmware, WLAN module interface + control and data receive(RX)/transmit(TX) control. + config ATH10K_DEBUG bool "Atheros ath10k debugging" depends on ATH10K diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile index 930fadd940d8..25b23bf2c8e6 100644 --- a/drivers/net/wireless/ath/ath10k/Makefile +++ b/drivers/net/wireless/ath/ath10k/Makefile @@ -24,6 +24,9 @@ ath10k_core-$(CONFIG_PM) += wow.o obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o ath10k_pci-y += pci.o \ ce.o +obj-$(CONFIG_ATH10K_TARGET_SNOC) += ath10k_snoc.o +ath10k_snoc-y += snoc.o \ + ce.o ath10k_pci-$(CONFIG_ATH10K_AHB) += ahb.o diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c index 5f1b6b294b5f..34add97b55d2 100644 --- a/drivers/power/supply/qcom/battery.c +++ b/drivers/power/supply/qcom/battery.c @@ -42,6 +42,7 @@ struct pl_data { struct votable *fcc_votable; struct votable *fv_votable; struct votable *pl_disable_votable; + struct votable *pl_awake_votable; struct work_struct status_change_work; struct delayed_work pl_taper_work; struct power_supply *main_psy; @@ -82,7 +83,7 @@ enum { static void split_settled(struct pl_data *chip) { int slave_icl_pct; - int slave_ua; + int slave_ua = 0; union power_supply_propval pval = {0, }; int rc; @@ -94,11 +95,9 @@ static void split_settled(struct pl_data *chip) if (chip->pl_mode != POWER_SUPPLY_PARALLEL_USBIN_USBIN) return; - if (chip->main_psy) + if (!chip->main_psy) return; - slave_ua = 0; - if (!get_effective_result_locked(chip->pl_disable_votable)) { /* read the aicl settled value */ rc = power_supply_get_property(chip->main_psy, @@ -214,7 +213,7 @@ static void pl_taper_work(struct work_struct *work) if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER) { pl_dbg(chip, PR_PARALLEL, "master is taper charging; reducing slave FCC\n"); - __pm_stay_awake(chip->pl_ws); + vote(chip->pl_awake_votable, TAPER_END_VOTER, true, 0); /* Reduce the taper percent by 25 percent */ chip->taper_pct = chip->taper_pct * TAPER_RESIDUAL_PCT / 100; rerun_election(chip->fcc_votable); @@ -231,7 +230,7 @@ static void pl_taper_work(struct work_struct *work) pl_dbg(chip, PR_PARALLEL, "master is fast charging; waiting for next taper\n"); done: - __pm_relax(chip->pl_ws); + vote(chip->pl_awake_votable, TAPER_END_VOTER, false, 0); } /********* @@ -375,15 +374,17 @@ static int pl_disable_vote_callback(struct votable *votable, if (!pl_disable) { /* enable */ rerun_election(chip->fv_votable); rerun_election(chip->fcc_votable); - - if (chip->pl_psy) { - pval.intval = 0; - rc = power_supply_set_property(chip->pl_psy, - POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval); - if (rc < 0) - pr_err("Couldn't change slave suspend state rc=%d\n", - rc); - } + /* + * Enable will be called with a valid pl_psy always. The + * PARALLEL_PSY_VOTER keeps it disabled unless a pl_psy + * is seen. + */ + pval.intval = 0; + rc = power_supply_set_property(chip->pl_psy, + POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval); + if (rc < 0) + pr_err("Couldn't change slave suspend state rc=%d\n", + rc); if (chip->pl_mode == POWER_SUPPLY_PARALLEL_USBIN_USBIN) split_settled(chip); @@ -406,6 +407,7 @@ static int pl_disable_vote_callback(struct votable *votable, if (chip->pl_mode == POWER_SUPPLY_PARALLEL_USBIN_USBIN) split_settled(chip); + /* pl_psy may be NULL while in the disable branch */ if (chip->pl_psy) { pval.intval = 1; rc = power_supply_set_property(chip->pl_psy, @@ -424,6 +426,20 @@ static int pl_disable_vote_callback(struct votable *votable, return 0; } +static int pl_awake_vote_callback(struct votable *votable, + void *data, int awake, const char *client) +{ + struct pl_data *chip = data; + + if (awake) + __pm_stay_awake(chip->pl_ws); + else + __pm_relax(chip->pl_ws); + + pr_debug("client: %s awake: %d\n", client, awake); + return 0; +} + static bool is_main_available(struct pl_data *chip) { if (!chip->main_psy) @@ -500,15 +516,6 @@ static void handle_main_charge_type(struct pl_data *chip) return; } - /* handle fast/taper charge entry */ - if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER - || pval.intval == POWER_SUPPLY_CHARGE_TYPE_FAST) { - pl_dbg(chip, PR_PARALLEL, "chg_state enabling parallel\n"); - vote(chip->pl_disable_votable, CHG_STATE_VOTER, false, 0); - chip->charge_type = pval.intval; - return; - } - /* handle taper charge entry */ if (chip->charge_type == POWER_SUPPLY_CHARGE_TYPE_FAST && (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER)) { @@ -518,6 +525,15 @@ static void handle_main_charge_type(struct pl_data *chip) return; } + /* handle fast/taper charge entry */ + if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER + || pval.intval == POWER_SUPPLY_CHARGE_TYPE_FAST) { + pl_dbg(chip, PR_PARALLEL, "chg_state enabling parallel\n"); + vote(chip->pl_disable_votable, CHG_STATE_VOTER, false, 0); + chip->charge_type = pval.intval; + return; + } + /* remember the new state only if it isn't any of the above */ chip->charge_type = pval.intval; } @@ -671,6 +687,14 @@ static int pl_init(void) vote(chip->pl_disable_votable, TAPER_END_VOTER, false, 0); vote(chip->pl_disable_votable, PARALLEL_PSY_VOTER, true, 0); + chip->pl_awake_votable = create_votable("PL_AWAKE", VOTE_SET_ANY, + pl_awake_vote_callback, + chip); + if (IS_ERR(chip->pl_awake_votable)) { + rc = PTR_ERR(chip->pl_disable_votable); + goto destroy_votable; + } + INIT_WORK(&chip->status_change_work, status_change_work); INIT_DELAYED_WORK(&chip->pl_taper_work, pl_taper_work); @@ -701,6 +725,7 @@ static int pl_init(void) unreg_notifier: power_supply_unreg_notifier(&chip->nb); destroy_votable: + destroy_votable(chip->pl_awake_votable); destroy_votable(chip->pl_disable_votable); destroy_votable(chip->fv_votable); destroy_votable(chip->fcc_votable); @@ -716,6 +741,7 @@ static void pl_deinit(void) struct pl_data *chip = the_chip; power_supply_unreg_notifier(&chip->nb); + destroy_votable(chip->pl_awake_votable); destroy_votable(chip->pl_disable_votable); destroy_votable(chip->fv_votable); destroy_votable(chip->fcc_votable); diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c index 7ffa583ca01d..744cbde7fc7f 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen3.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c @@ -2285,7 +2285,6 @@ reschedule: msecs_to_jiffies(BATT_AVG_POLL_PERIOD_MS)); } -#define DECI_TAU_SCALE 13 #define HOURS_TO_SECONDS 3600 #define OCV_SLOPE_UV 10869 #define MILLI_UNIT 1000 @@ -2294,7 +2293,7 @@ static int fg_get_time_to_full(struct fg_chip *chip, int *val) { int rc, ibatt_avg, vbatt_avg, rbatt, msoc, ocv_cc2cv, full_soc, act_cap_uah; - s32 i_cc2cv, soc_cc2cv, ln_val; + s32 i_cc2cv, soc_cc2cv, ln_val, centi_tau_scale; s64 t_predicted_cc = 0, t_predicted_cv = 0; if (chip->bp.float_volt_uv <= 0) { @@ -2417,15 +2416,20 @@ skip_cc_estimate: /* CV estimate starts here */ if (chip->charge_type >= POWER_SUPPLY_CHARGE_TYPE_TAPER) - ln_val = ibatt_avg / abs(chip->dt.sys_term_curr_ma); + ln_val = ibatt_avg / (abs(chip->dt.sys_term_curr_ma) + 200); else - ln_val = i_cc2cv / abs(chip->dt.sys_term_curr_ma); + ln_val = i_cc2cv / (abs(chip->dt.sys_term_curr_ma) + 200); + + if (msoc < 95) + centi_tau_scale = 100; + else + centi_tau_scale = 20 * (100 - msoc); fg_dbg(chip, FG_TTF, "ln_in=%d\n", ln_val); rc = fg_lerp(fg_ln_table, ARRAY_SIZE(fg_ln_table), ln_val, &ln_val); fg_dbg(chip, FG_TTF, "ln_out=%d\n", ln_val); t_predicted_cv = div_s64((s64)act_cap_uah * rbatt, MICRO_UNIT); - t_predicted_cv = div_s64(t_predicted_cv * DECI_TAU_SCALE, 10); + t_predicted_cv = div_s64(t_predicted_cv * centi_tau_scale, 100); t_predicted_cv = div_s64(t_predicted_cv * ln_val, MILLI_UNIT); t_predicted_cv = div_s64(t_predicted_cv * HOURS_TO_SECONDS, MICRO_UNIT); fg_dbg(chip, FG_TTF, "t_predicted_cv=%lld\n", t_predicted_cv); diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index 022ed49ce6eb..3e939c5ffba1 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -505,7 +505,7 @@ static int smblib_notifier_call(struct notifier_block *nb, schedule_work(&chg->bms_update_work); } - if (!chg->pl.psy && !strcmp(psy->desc->name, "usb-parallel")) + if (!chg->pl.psy && !strcmp(psy->desc->name, "parallel")) chg->pl.psy = psy; return NOTIFY_OK; @@ -3366,6 +3366,25 @@ static int smblib_create_votables(struct smb_charger *chg) { int rc = 0; + chg->fcc_votable = find_votable("FCC"); + if (!chg->fcc_votable) { + rc = -EPROBE_DEFER; + return rc; + } + + chg->fv_votable = find_votable("FV"); + if (!chg->fv_votable) { + rc = -EPROBE_DEFER; + return rc; + } + + chg->pl_disable_votable = find_votable("PL_DISABLE"); + if (!chg->pl_disable_votable) { + rc = -EPROBE_DEFER; + return rc; + } + vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, true, 0); + chg->usb_suspend_votable = create_votable("USB_SUSPEND", VOTE_SET_ANY, smblib_usb_suspend_vote_callback, chg); @@ -3390,18 +3409,6 @@ static int smblib_create_votables(struct smb_charger *chg) return rc; } - chg->fcc_votable = find_votable("FCC"); - if (!chg->fcc_votable) { - rc = -EPROBE_DEFER; - return rc; - } - - chg->fv_votable = find_votable("FV"); - if (!chg->fv_votable) { - rc = -EPROBE_DEFER; - return rc; - } - chg->usb_icl_votable = create_votable("USB_ICL", VOTE_MIN, smblib_usb_icl_vote_callback, chg); @@ -3441,13 +3448,6 @@ static int smblib_create_votables(struct smb_charger *chg) return rc; } - chg->pl_disable_votable = find_votable("PL_DISABLE"); - if (!chg->pl_disable_votable) { - rc = -EPROBE_DEFER; - return rc; - } - vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, true, 0); - chg->chg_disable_votable = create_votable("CHG_DISABLE", VOTE_SET_ANY, smblib_chg_disable_vote_callback, chg); @@ -3566,8 +3566,7 @@ int smblib_init(struct smb_charger *chg) } chg->bms_psy = power_supply_get_by_name("bms"); - chg->pl.psy = power_supply_get_by_name("usb-parallel"); - + chg->pl.psy = power_supply_get_by_name("parallel"); break; case PARALLEL_SLAVE: break; diff --git a/drivers/soc/qcom/glink_ssr.c b/drivers/soc/qcom/glink_ssr.c index 4d94e6446505..5e2dbc8b1d20 100644 --- a/drivers/soc/qcom/glink_ssr.c +++ b/drivers/soc/qcom/glink_ssr.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -339,6 +339,7 @@ void close_ch_worker(struct work_struct *work) BUG_ON(!ss_info->cb_data); kfree(ss_info->cb_data); + ss_info->cb_data = NULL; kfree(close_work); } diff --git a/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c b/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c index 45ac48eb2241..19974b61ec1c 100644 --- a/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c +++ b/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016 The Linux Foundation. +/* Copyright (c) 2016-2017 The Linux Foundation. * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -17,7 +17,6 @@ #include <linux/uaccess.h> #include <linux/spinlock.h> #include <linux/mutex.h> -#include <linux/list.h> #include <linux/sched.h> #include <linux/wait.h> #include <linux/errno.h> @@ -34,16 +33,10 @@ #define APR_MAXIMUM_NUM_OF_RETRIES 2 struct apr_tx_buf { - struct list_head list; struct apr_pkt_priv pkt_priv; char buf[APR_MAX_BUF]; }; -struct apr_buf_list { - struct list_head list; - spinlock_t lock; -}; - struct link_state { uint32_t dest; void *handle; @@ -52,7 +45,6 @@ struct link_state { }; static struct link_state link_state[APR_DEST_MAX]; -static struct apr_buf_list buf_list; static char *svc_names[APR_DEST_MAX][APR_CLIENT_MAX] = { { @@ -68,44 +60,37 @@ static char *svc_names[APR_DEST_MAX][APR_CLIENT_MAX] = { static struct apr_svc_ch_dev apr_svc_ch[APR_DL_MAX][APR_DEST_MAX][APR_CLIENT_MAX]; -static struct apr_tx_buf *apr_get_free_buf(int len) +static struct apr_tx_buf *apr_alloc_buf(int len) { - struct apr_tx_buf *tx_buf; - unsigned long flags; if (len > APR_MAX_BUF) { pr_err("%s: buf too large [%d]\n", __func__, len); return ERR_PTR(-EINVAL); } - spin_lock_irqsave(&buf_list.lock, flags); - if (list_empty(&buf_list.list)) { - spin_unlock_irqrestore(&buf_list.lock, flags); - pr_err("%s: No buf available\n", __func__); - return ERR_PTR(-ENOMEM); - } - - tx_buf = list_first_entry(&buf_list.list, struct apr_tx_buf, list); - list_del(&tx_buf->list); - spin_unlock_irqrestore(&buf_list.lock, flags); - - return tx_buf; + return kzalloc(sizeof(struct apr_tx_buf), GFP_ATOMIC); } -static void apr_buf_add_tail(const void *buf) +static void apr_free_buf(const void *ptr) { - struct apr_tx_buf *list; - unsigned long flags; - if (!buf) + struct apr_pkt_priv *apr_pkt_priv = (struct apr_pkt_priv *)ptr; + struct apr_tx_buf *tx_buf; + + if (!apr_pkt_priv) { + pr_err("%s: Invalid apr_pkt_priv\n", __func__); return; + } - spin_lock_irqsave(&buf_list.lock, flags); - list = container_of((void *)buf, struct apr_tx_buf, buf); - list_add_tail(&list->list, &buf_list.list); - spin_unlock_irqrestore(&buf_list.lock, flags); + if (apr_pkt_priv->pkt_owner == APR_PKT_OWNER_DRIVER) { + tx_buf = container_of((void *)apr_pkt_priv, + struct apr_tx_buf, pkt_priv); + pr_debug("%s: Freeing buffer %pK", __func__, tx_buf); + kfree(tx_buf); + } } + static int __apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data, struct apr_pkt_priv *pkt_priv, int len) { @@ -137,7 +122,7 @@ int apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data, return -EINVAL; if (pkt_priv->pkt_owner == APR_PKT_OWNER_DRIVER) { - tx_buf = apr_get_free_buf(len); + tx_buf = apr_alloc_buf(len); if (IS_ERR_OR_NULL(tx_buf)) { rc = -EINVAL; goto exit; @@ -160,7 +145,7 @@ int apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data, if (rc < 0) { pr_err("%s: Unable to send the packet, rc:%d\n", __func__, rc); if (pkt_priv->pkt_owner == APR_PKT_OWNER_DRIVER) - apr_buf_add_tail(pkt_data); + kfree(tx_buf); } exit: return rc; @@ -189,39 +174,17 @@ void apr_tal_notify_rx(void *handle, const void *priv, const void *pkt_priv, static void apr_tal_notify_tx_abort(void *handle, const void *priv, const void *pkt_priv) { - struct apr_pkt_priv *apr_pkt_priv_ptr = - (struct apr_pkt_priv *)pkt_priv; - struct apr_tx_buf *list_node; - - if (!apr_pkt_priv_ptr) { - pr_err("%s: Invalid pkt_priv\n", __func__); - return; - } - - pr_debug("%s: tx_abort received for apr_pkt_priv_ptr:%pK\n", - __func__, apr_pkt_priv_ptr); - - if (apr_pkt_priv_ptr->pkt_owner == APR_PKT_OWNER_DRIVER) { - list_node = container_of(apr_pkt_priv_ptr, - struct apr_tx_buf, pkt_priv); - apr_buf_add_tail(list_node->buf); - } + pr_debug("%s: tx_abort received for pkt_priv:%pK\n", + __func__, pkt_priv); + apr_free_buf(pkt_priv); } void apr_tal_notify_tx_done(void *handle, const void *priv, const void *pkt_priv, const void *ptr) { - struct apr_pkt_priv *apr_pkt_priv = (struct apr_pkt_priv *)pkt_priv; - - if (!pkt_priv || !ptr) { - pr_err("%s: Invalid pkt_priv or ptr\n", __func__); - return; - } - - pr_debug("%s: tx_done received\n", __func__); - - if (apr_pkt_priv->pkt_owner == APR_PKT_OWNER_DRIVER) - apr_buf_add_tail(ptr); + pr_debug("%s: tx_done received for pkt_priv:%pK\n", + __func__, pkt_priv); + apr_free_buf(pkt_priv); } bool apr_tal_notify_rx_intent_req(void *handle, const void *priv, @@ -457,8 +420,6 @@ static struct glink_link_info lpass_link_info = { static int __init apr_tal_init(void) { int i, j, k; - struct apr_tx_buf *buf; - struct list_head *ptr, *next; for (i = 0; i < APR_DL_MAX; i++) { for (j = 0; j < APR_DEST_MAX; j++) { @@ -474,21 +435,6 @@ static int __init apr_tal_init(void) for (i = 0; i < APR_DEST_MAX; i++) init_waitqueue_head(&link_state[i].wait); - spin_lock_init(&buf_list.lock); - INIT_LIST_HEAD(&buf_list.list); - for (i = 0; i < APR_NUM_OF_TX_BUF; i++) { - buf = kzalloc(sizeof(struct apr_tx_buf), GFP_KERNEL); - if (!buf) { - pr_err("%s: Unable to allocate tx buf\n", __func__); - goto tx_buf_alloc_fail; - } - - INIT_LIST_HEAD(&buf->list); - spin_lock(&buf_list.lock); - list_add_tail(&buf->list, &buf_list.list); - spin_unlock(&buf_list.lock); - } - link_state[APR_DEST_MODEM].link_state = GLINK_LINK_STATE_DOWN; link_state[APR_DEST_MODEM].handle = glink_register_link_state_cb(&mpss_link_info, NULL); @@ -502,13 +448,5 @@ static int __init apr_tal_init(void) pr_err("%s: Unable to register lpass link state\n", __func__); return 0; - -tx_buf_alloc_fail: - list_for_each_safe(ptr, next, &buf_list.list) { - buf = list_entry(ptr, struct apr_tx_buf, list); - list_del(&buf->list); - kfree(buf); - } - return -ENOMEM; } device_initcall(apr_tal_init); diff --git a/drivers/thermal/msm_lmh_dcvs.c b/drivers/thermal/msm_lmh_dcvs.c index 7758750516f8..4ebfc713cb28 100644 --- a/drivers/thermal/msm_lmh_dcvs.c +++ b/drivers/thermal/msm_lmh_dcvs.c @@ -68,6 +68,8 @@ _max = (_val) & 0x3FF; \ _max *= 19200; \ } while (0) +#define FREQ_KHZ_TO_HZ(_val) ((_val) * 1000) +#define FREQ_HZ_TO_KHZ(_val) ((_val) / 1000) enum lmh_hw_trips { LIMITS_TRIP_LO, @@ -114,6 +116,7 @@ static uint32_t msm_lmh_mitigation_notify(struct msm_lmh_dcvs_hw *hw) uint32_t max_limit = 0, val = 0; struct device *cpu_dev = NULL; unsigned long freq_val; + struct dev_pm_opp *opp_entry; val = readl_relaxed(hw->osm_hw_reg); dcvsh_get_frequency(val, max_limit); @@ -124,11 +127,23 @@ static uint32_t msm_lmh_mitigation_notify(struct msm_lmh_dcvs_hw *hw) goto notify_exit; } - freq_val = max_limit; + freq_val = FREQ_KHZ_TO_HZ(max_limit); rcu_read_lock(); - dev_pm_opp_find_freq_floor(cpu_dev, &freq_val); + opp_entry = dev_pm_opp_find_freq_floor(cpu_dev, &freq_val); + /* + * Hardware mitigation frequency can be lower than the lowest + * possible CPU frequency. In that case freq floor call will + * fail with -ERANGE and we need to match to the lowest + * frequency using freq_ceil. + */ + if (IS_ERR(opp_entry) && PTR_ERR(opp_entry) == -ERANGE) { + opp_entry = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_val); + if (IS_ERR(opp_entry)) + dev_err(cpu_dev, "frequency:%lu. opp error:%ld\n", + freq_val, PTR_ERR(opp_entry)); + } rcu_read_unlock(); - max_limit = freq_val; + max_limit = FREQ_HZ_TO_KHZ(freq_val); sched_update_cpu_freq_min_max(&hw->core_map, 0, max_limit); trace_lmh_dcvs_freq(cpumask_first(&hw->core_map), max_limit); diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index d03678a02185..7f1ae5cf9909 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -25,6 +25,7 @@ int dwc3_host_init(struct dwc3 *dwc) struct platform_device *xhci; struct usb_xhci_pdata pdata; int ret; + struct device_node *node = dwc->dev->of_node; xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO); if (!xhci) { @@ -52,6 +53,11 @@ int dwc3_host_init(struct dwc3 *dwc) pdata.usb3_lpm_capable = dwc->usb3_lpm_capable; + ret = of_property_read_u32(node, "xhci-imod-value", + &pdata.imod_interval); + if (ret) + pdata.imod_interval = 0; /* use default xhci.c value */ + ret = platform_device_add_data(xhci, &pdata, sizeof(pdata)); if (ret) { dev_err(dwc->dev, "couldn't add platform data to xHCI device\n"); diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 1221a80e0bdc..05d96fd8c07c 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -138,6 +138,8 @@ static int xhci_plat_probe(struct platform_device *pdev) struct clk *clk; int ret; int irq; + u32 temp, imod; + unsigned long flags; if (usb_disabled()) return -ENODEV; @@ -256,6 +258,18 @@ static int xhci_plat_probe(struct platform_device *pdev) device_wakeup_enable(&xhci->shared_hcd->self.root_hub->dev); + /* override imod interval if specified */ + if (pdata && pdata->imod_interval) { + imod = pdata->imod_interval & ER_IRQ_INTERVAL_MASK; + spin_lock_irqsave(&xhci->lock, flags); + temp = readl_relaxed(&xhci->ir_set->irq_control); + temp &= ~ER_IRQ_INTERVAL_MASK; + temp |= imod; + writel_relaxed(temp, &xhci->ir_set->irq_control); + spin_unlock_irqrestore(&xhci->lock, flags); + dev_dbg(&pdev->dev, "%s: imod set to %u\n", __func__, imod); + } + ret = device_create_file(&pdev->dev, &dev_attr_config_imod); if (ret) dev_err(&pdev->dev, "%s: unable to create imod sysfs entry\n", diff --git a/include/linux/qdsp6v2/apr_tal.h b/include/linux/qdsp6v2/apr_tal.h index c2c49dd748de..bf324064960b 100644 --- a/include/linux/qdsp6v2/apr_tal.h +++ b/include/linux/qdsp6v2/apr_tal.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2011, 2016 The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2011, 2016-2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -32,7 +32,6 @@ #if defined(CONFIG_MSM_QDSP6_APRV2_GLINK) || \ defined(CONFIG_MSM_QDSP6_APRV3_GLINK) #define APR_MAX_BUF 512 -#define APR_NUM_OF_TX_BUF 30 #else #define APR_MAX_BUF 8092 #endif diff --git a/include/linux/usb/xhci_pdriver.h b/include/linux/usb/xhci_pdriver.h index 376654b5b0f7..a44b53c33e75 100644 --- a/include/linux/usb/xhci_pdriver.h +++ b/include/linux/usb/xhci_pdriver.h @@ -19,9 +19,13 @@ * @usb3_lpm_capable: determines if this xhci platform supports USB3 * LPM capability * + * @imod_interval: minimum inter-interrupt interval. Specified in + * 250nsec increments. + * */ struct usb_xhci_pdata { unsigned usb3_lpm_capable:1; + unsigned imod_interval; }; #endif /* __USB_CORE_XHCI_PDRIVER_H */ diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h index a047a33334d2..1f8bba7e9ab7 100644 --- a/include/sound/apr_audio-v2.h +++ b/include/sound/apr_audio-v2.h @@ -42,6 +42,8 @@ struct param_outband { #define ADM_MATRIX_ID_AUDIO_TX 1 #define ADM_MATRIX_ID_COMPRESSED_AUDIO_RX 2 + +#define ADM_MATRIX_ID_LISTEN_TX 4 /* Enumeration for an audio Tx matrix ID.*/ #define ADM_MATRIX_ID_AUDIOX 1 @@ -9044,6 +9046,7 @@ struct asm_aptx_dec_fmt_blk_v2 { #define LSM_SESSION_EVENT_DETECTION_STATUS_V2 (0x00012B01) #define LSM_DATA_EVENT_READ_DONE (0x00012B02) #define LSM_DATA_EVENT_STATUS (0x00012B03) +#define LSM_SESSION_EVENT_DETECTION_STATUS_V3 (0x00012B04) #define LSM_MODULE_ID_VOICE_WAKEUP (0x00012C00) #define LSM_PARAM_ID_ENDPOINT_DETECT_THRESHOLD (0x00012C01) @@ -9056,6 +9059,12 @@ struct asm_aptx_dec_fmt_blk_v2 { #define LSM_PARAM_ID_LAB_ENABLE (0x00012C09) #define LSM_PARAM_ID_LAB_CONFIG (0x00012C0A) #define LSM_MODULE_ID_FRAMEWORK (0x00012C0E) +#define LSM_PARAM_ID_SWMAD_CFG (0x00012C18) +#define LSM_PARAM_ID_SWMAD_MODEL (0x00012C19) +#define LSM_PARAM_ID_SWMAD_ENABLE (0x00012C1A) +#define LSM_PARAM_ID_POLLING_ENABLE (0x00012C1B) +#define LSM_PARAM_ID_MEDIA_FMT (0x00012C1E) +#define LSM_PARAM_ID_FWK_MODE_CONFIG (0x00012C27) /* HW MAD specific */ #define AFE_MODULE_HW_MAD (0x00010230) @@ -10172,6 +10181,7 @@ enum { COMPRESSED_PASSTHROUGH, COMPRESSED_PASSTHROUGH_CONVERT, COMPRESSED_PASSTHROUGH_DSD, + LISTEN, }; #define AUDPROC_MODULE_ID_COMPRESSED_MUTE 0x00010770 diff --git a/include/sound/cpe_core.h b/include/sound/cpe_core.h index 323a63fd6238..846cf819b9e5 100644 --- a/include/sound/cpe_core.h +++ b/include/sound/cpe_core.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, 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 @@ -162,7 +162,7 @@ struct wcd_cpe_lsm_ops { int (*lsm_set_one_param)(void *core_handle, struct cpe_lsm_session *session, struct lsm_params_info *p_info, - void *data, enum LSM_PARAM_TYPE param_type); + void *data, uint32_t param_type); void (*lsm_get_snd_model_offset) (void *core_handle, struct cpe_lsm_session *, size_t *offset); diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h index 8c7da3b9838d..25376315dd20 100644 --- a/include/sound/q6adm-v2.h +++ b/include/sound/q6adm-v2.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -96,7 +96,7 @@ int adm_unmap_rtac_block(uint32_t *mem_map_handle); int adm_close(int port, int topology, int perf_mode); int adm_matrix_map(int path, struct route_payload payload_map, - int perf_mode); + int perf_mode, uint32_t passthr_mode); int adm_connect_afe_port(int mode, int session_id, int port_id); diff --git a/include/sound/q6lsm.h b/include/sound/q6lsm.h index fb848bc70873..4805246766d6 100644 --- a/include/sound/q6lsm.h +++ b/include/sound/q6lsm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, 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 @@ -21,6 +21,10 @@ #define MAX_NUM_CONFIDENCE 20 +#define ADM_LSM_PORT_ID 0xADCB + +#define LSM_MAX_NUM_CHANNELS 8 + typedef void (*lsm_app_cb)(uint32_t opcode, uint32_t token, uint32_t *payload, void *priv); @@ -49,11 +53,12 @@ struct lsm_lab_buffer { uint32_t mem_map_handle; }; -struct lsm_lab_hw_params { +struct lsm_hw_params { u16 sample_rate; u16 sample_size; u32 buf_sz; u32 period_count; + u16 num_chs; }; struct lsm_client { @@ -79,8 +84,12 @@ struct lsm_client { bool lab_enable; bool lab_started; struct lsm_lab_buffer *lab_buffer; - struct lsm_lab_hw_params hw_params; + struct lsm_hw_params hw_params; bool use_topology; + int session_state; + bool poll_enable; + int perf_mode; + uint32_t event_mode; }; struct lsm_stream_cmd_open_tx { @@ -134,6 +143,27 @@ struct lsm_param_connect_to_port { uint16_t reserved; } __packed; +struct lsm_param_poll_enable { + struct lsm_param_payload_common common; + uint32_t minor_version; + /* indicates to voice wakeup that HW MAD/SW polling is enabled or not */ + uint32_t polling_enable; +} __packed; + +struct lsm_param_fwk_mode_cfg { + struct lsm_param_payload_common common; + uint32_t minor_version; + uint32_t mode; +} __packed; + +struct lsm_param_media_fmt { + struct lsm_param_payload_common common; + uint32_t minor_version; + uint32_t sample_rate; + uint16_t num_channels; + uint16_t bit_width; + uint8_t channel_mapping[LSM_MAX_NUM_CHANNELS]; +} __packed; /* * This param cannot be sent in this format. @@ -163,11 +193,22 @@ struct lsm_cmd_set_params_conf { struct lsm_param_min_confidence_levels conf_payload; } __packed; -struct lsm_cmd_set_opmode_connectport { +struct lsm_cmd_set_params_opmode { + struct apr_hdr msg_hdr; + struct lsm_set_params_hdr params_hdr; + struct lsm_param_op_mode op_mode; +} __packed; + +struct lsm_cmd_set_connectport { + struct apr_hdr msg_hdr; + struct lsm_set_params_hdr params_hdr; + struct lsm_param_connect_to_port connect_to_port; +} __packed; + +struct lsm_cmd_poll_enable { struct apr_hdr msg_hdr; struct lsm_set_params_hdr params_hdr; - struct lsm_param_connect_to_port connect_to_port; - struct lsm_param_op_mode op_mode; + struct lsm_param_poll_enable poll_enable; } __packed; struct lsm_param_epd_thres { @@ -250,6 +291,19 @@ struct lsm_cmd_read_done { uint32_t flags; } __packed; +struct lsm_cmd_set_fwk_mode_cfg { + struct apr_hdr msg_hdr; + struct lsm_set_params_hdr params_hdr; + struct lsm_param_fwk_mode_cfg fwk_mode_cfg; +} __packed; + +struct lsm_cmd_set_media_fmt { + struct apr_hdr msg_hdr; + struct lsm_set_params_hdr params_hdr; + struct lsm_param_media_fmt media_fmt; +} __packed; + + struct lsm_client *q6lsm_client_alloc(lsm_app_cb cb, void *priv); void q6lsm_client_free(struct lsm_client *client); int q6lsm_open(struct lsm_client *client, uint16_t app_id); @@ -274,8 +328,11 @@ int q6lsm_read(struct lsm_client *client, struct lsm_cmd_read *read); int q6lsm_lab_buffer_alloc(struct lsm_client *client, bool alloc); int q6lsm_set_one_param(struct lsm_client *client, struct lsm_params_info *p_info, void *data, - enum LSM_PARAM_TYPE param_type); + uint32_t param_type); void q6lsm_sm_set_param_data(struct lsm_client *client, struct lsm_params_info *p_info, size_t *offset); +int q6lsm_set_port_connected(struct lsm_client *client); +int q6lsm_set_fwk_mode_cfg(struct lsm_client *client, uint32_t event_mode); +int q6lsm_set_media_fmt_params(struct lsm_client *client); #endif /* __Q6LSM_H__ */ diff --git a/include/uapi/media/msm_vidc.h b/include/uapi/media/msm_vidc.h index b259bdef8a93..e9370cb660b2 100644 --- a/include/uapi/media/msm_vidc.h +++ b/include/uapi/media/msm_vidc.h @@ -245,7 +245,7 @@ enum msm_vidc_extradata_type { MSM_VIDC_EXTRADATA_DIGITAL_ZOOM = 0x07000010, #define MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO \ MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO - MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO = 0x070000011, + MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO = 0x00000014, MSM_VIDC_EXTRADATA_MULTISLICE_INFO = 0x7F100000, MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB = 0x7F100001, MSM_VIDC_EXTRADATA_INDEX = 0x7F100002, diff --git a/include/uapi/sound/lsm_params.h b/include/uapi/sound/lsm_params.h index eafdc117413a..9ca5930475ba 100644 --- a/include/uapi/sound/lsm_params.h +++ b/include/uapi/sound/lsm_params.h @@ -1,6 +1,9 @@ #ifndef _UAPI_LSM_PARAMS_H__ #define _UAPI_LSM_PARAMS_H__ +#define LSM_POLLING_ENABLE_SUPPORT +#define LSM_EVENT_TIMESTAMP_MODE_SUPPORT + #include <linux/types.h> #include <sound/asound.h> @@ -18,6 +21,19 @@ #define LSM_OUT_TRANSFER_MODE_RT (0) #define LSM_OUT_TRANSFER_MODE_FTRT (1) +#define LSM_ENDPOINT_DETECT_THRESHOLD (0) +#define LSM_OPERATION_MODE (1) +#define LSM_GAIN (2) +#define LSM_MIN_CONFIDENCE_LEVELS (3) +#define LSM_REG_SND_MODEL (4) +#define LSM_DEREG_SND_MODEL (5) +#define LSM_CUSTOM_PARAMS (6) +#define LSM_POLLING_ENABLE (7) +#define LSM_PARAMS_MAX (LSM_POLLING_ENABLE + 1) + +#define LSM_EVENT_NON_TIME_STAMP_MODE (0) +#define LSM_EVENT_TIME_STAMP_MODE (1) + enum lsm_app_id { LSM_VOICE_WAKEUP_APP_ID = 1, LSM_VOICE_WAKEUP_APP_ID_V2 = 2, @@ -35,18 +51,6 @@ enum lsm_vw_status { LSM_VOICE_WAKEUP_STATUS_REJECTED }; -enum LSM_PARAM_TYPE { - LSM_ENDPOINT_DETECT_THRESHOLD = 0, - LSM_OPERATION_MODE, - LSM_GAIN, - LSM_MIN_CONFIDENCE_LEVELS, - LSM_REG_SND_MODEL, - LSM_DEREG_SND_MODEL, - LSM_CUSTOM_PARAMS, - /* driver ioctl will parse only so many params */ - LSM_PARAMS_MAX, -}; - /* * Data for LSM_ENDPOINT_DETECT_THRESHOLD param_type * @epd_begin: Begin threshold @@ -75,6 +79,14 @@ struct snd_lsm_gain { __u16 gain; }; +/* + * Data for LSM_POLLING_ENABLE param_type + * @poll_en: Polling enable or disable + */ +struct snd_lsm_poll_enable { + bool poll_en; +}; + struct snd_lsm_sound_model_v2 { __u8 __user *data; @@ -95,11 +107,20 @@ struct snd_lsm_event_status { __u8 payload[0]; }; +struct snd_lsm_event_status_v3 { + __u32 timestamp_lsw; + __u32 timestamp_msw; + __u16 status; + __u16 payload_size; + __u8 payload[0]; +}; + struct snd_lsm_detection_params { __u8 *conf_level; enum lsm_detection_mode detect_mode; __u8 num_confidence_levels; bool detect_failure; + bool poll_enable; }; /* @@ -122,7 +143,7 @@ struct lsm_params_info { __u32 param_id; __u32 param_size; __u8 __user *param_data; - enum LSM_PARAM_TYPE param_type; + uint32_t param_type; }; /* @@ -171,5 +192,9 @@ struct snd_lsm_output_format_cfg { struct snd_lsm_module_params) #define SNDRV_LSM_OUT_FORMAT_CFG _IOW('U', 0x0C, \ struct snd_lsm_output_format_cfg) +#define SNDRV_LSM_SET_PORT _IO('U', 0x0D) +#define SNDRV_LSM_SET_FWK_MODE_CONFIG _IOW('U', 0x0E, uint32_t) +#define SNDRV_LSM_EVENT_STATUS_V3 _IOW('U', 0x0F, \ + struct snd_lsm_event_status_v3) #endif diff --git a/kernel/sched/boost.c b/kernel/sched/boost.c index fcfda385b74a..5bdd51b1e55e 100644 --- a/kernel/sched/boost.c +++ b/kernel/sched/boost.c @@ -156,9 +156,6 @@ void sched_boost_parse_dt(void) struct device_node *sn; const char *boost_policy; - if (!sched_enable_hmp) - return; - sn = of_find_node_by_path("/sched-hmp"); if (!sn) return; @@ -175,9 +172,6 @@ int sched_set_boost(int type) { int ret = 0; - if (!sched_enable_hmp) - return -EINVAL; - mutex_lock(&boost_mutex); if (verify_boost_params(sysctl_sched_boost, type)) @@ -197,9 +191,6 @@ int sched_boost_handler(struct ctl_table *table, int write, unsigned int *data = (unsigned int *)table->data; unsigned int old_val; - if (!sched_enable_hmp) - return -EINVAL; - mutex_lock(&boost_mutex); old_val = *data; diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 672ed90fc879..3fcadbae663d 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3025,8 +3025,9 @@ void sched_exec(void) unsigned long flags; int dest_cpu, curr_cpu; - if (sched_enable_hmp) - return; +#ifdef CONFIG_SCHED_HMP + return; +#endif raw_spin_lock_irqsave(&p->pi_lock, flags); curr_cpu = task_cpu(p); @@ -8215,8 +8216,9 @@ void __init sched_init(void) int i, j; unsigned long alloc_size = 0, ptr; - if (sched_enable_hmp) - pr_info("HMP scheduling enabled.\n"); +#ifdef CONFIG_SCHED_HMP + pr_info("HMP scheduling enabled.\n"); +#endif BUG_ON(num_possible_cpus() > BITS_PER_LONG); diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index ac4c3f1d144a..6f68b0e19c4a 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3332,9 +3332,9 @@ void _inc_hmp_sched_stats_fair(struct rq *rq, * inc/dec_nr_big_task and inc/dec_cumulative_runnable_avg called * from inc_cfs_rq_hmp_stats() have similar checks), we gain a bit on * efficiency by short-circuiting for_each_sched_entity() loop when - * !sched_enable_hmp || sched_disable_window_stats + * sched_disable_window_stats */ - if (!sched_enable_hmp || sched_disable_window_stats) + if (sched_disable_window_stats) return; for_each_sched_entity(se) { @@ -3357,7 +3357,7 @@ _dec_hmp_sched_stats_fair(struct rq *rq, struct task_struct *p, int change_cra) struct sched_entity *se = &p->se; /* See comment on efficiency in _inc_hmp_sched_stats_fair */ - if (!sched_enable_hmp || sched_disable_window_stats) + if (sched_disable_window_stats) return; for_each_sched_entity(se) { @@ -3482,8 +3482,7 @@ static inline int migration_needed(struct task_struct *p, int cpu) int nice; struct related_thread_group *grp; - if (!sched_enable_hmp || p->state != TASK_RUNNING || - p->nr_cpus_allowed == 1) + if (p->state != TASK_RUNNING || p->nr_cpus_allowed == 1) return 0; /* No need to migrate task that is about to be throttled */ @@ -7024,8 +7023,9 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f int want_affine = 0; int sync = wake_flags & WF_SYNC; - if (sched_enable_hmp) - return select_best_cpu(p, prev_cpu, 0, sync); +#ifdef CONFIG_SCHED_HMP + return select_best_cpu(p, prev_cpu, 0, sync); +#endif if (sd_flag & SD_BALANCE_WAKE) want_affine = (!wake_wide(p) && task_fits_max(p, cpu) && @@ -9313,8 +9313,9 @@ static struct rq *find_busiest_queue(struct lb_env *env, unsigned long busiest_load = 0, busiest_capacity = 1; int i; - if (sched_enable_hmp) - return find_busiest_queue_hmp(env, group); +#ifdef CONFIG_SCHED_HMP + return find_busiest_queue_hmp(env, group); +#endif for_each_cpu_and(i, sched_group_cpus(group), env->cpus) { unsigned long capacity, wl; @@ -10120,8 +10121,9 @@ static inline int find_new_ilb(int type) { int ilb; - if (sched_enable_hmp) - return find_new_hmp_ilb(type); +#ifdef CONFIG_SCHED_HMP + return find_new_hmp_ilb(type); +#endif ilb = cpumask_first(nohz.idle_cpus_mask); @@ -10496,8 +10498,9 @@ static inline int _nohz_kick_needed(struct rq *rq, int cpu, int *type) if (likely(!atomic_read(&nohz.nr_cpus))) return 0; - if (sched_enable_hmp) - return _nohz_kick_needed_hmp(rq, cpu, type); +#ifdef CONFIG_SCHED_HMP + return _nohz_kick_needed_hmp(rq, cpu, type); +#endif if (time_before(now, nohz.next_balance)) return 0; diff --git a/kernel/sched/hmp.c b/kernel/sched/hmp.c index 0a74c8d23552..1c0defb34ae1 100644 --- a/kernel/sched/hmp.c +++ b/kernel/sched/hmp.c @@ -615,19 +615,6 @@ int register_cpu_cycle_counter_cb(struct cpu_cycle_counter_cb *cb) return 0; } -int __init set_sched_enable_hmp(char *str) -{ - int enable_hmp = 0; - - get_option(&str, &enable_hmp); - - sched_enable_hmp = !!enable_hmp; - - return 0; -} - -early_param("sched_enable_hmp", set_sched_enable_hmp); - /* Clear any HMP scheduler related requests pending from or on cpu */ void clear_hmp_request(int cpu) { @@ -869,9 +856,6 @@ unsigned int max_task_load(void) return sched_ravg_window; } -/* Use this knob to turn on or off HMP-aware task placement logic */ -unsigned int __read_mostly sched_enable_hmp; - /* A cpu can no longer accommodate more tasks if: * * rq->nr_running > sysctl_sched_spill_nr_run || @@ -1244,7 +1228,7 @@ unlock: void inc_nr_big_task(struct hmp_sched_stats *stats, struct task_struct *p) { - if (!sched_enable_hmp || sched_disable_window_stats) + if (sched_disable_window_stats) return; if (is_big_task(p)) @@ -1253,7 +1237,7 @@ void inc_nr_big_task(struct hmp_sched_stats *stats, struct task_struct *p) void dec_nr_big_task(struct hmp_sched_stats *stats, struct task_struct *p) { - if (!sched_enable_hmp || sched_disable_window_stats) + if (sched_disable_window_stats) return; if (is_big_task(p)) @@ -1322,7 +1306,7 @@ void fixup_nr_big_tasks(struct hmp_sched_stats *stats, u64 new_task_load; u64 old_task_load; - if (!sched_enable_hmp || sched_disable_window_stats) + if (sched_disable_window_stats) return; old_task_load = scale_load_to_cpu(task_load(p), task_cpu(p)); @@ -1432,9 +1416,6 @@ int sched_window_update_handler(struct ctl_table *table, int write, unsigned int *data = (unsigned int *)table->data; unsigned int old_val; - if (!sched_enable_hmp) - return -EINVAL; - mutex_lock(&policy_mutex); old_val = *data; @@ -1470,9 +1451,6 @@ int sched_hmp_proc_update_handler(struct ctl_table *table, int write, unsigned int *data = (unsigned int *)table->data; int update_task_count = 0; - if (!sched_enable_hmp) - return 0; - /* * The policy mutex is acquired with cpu_hotplug.lock * held from cpu_up()->cpufreq_governor_interactive()-> @@ -1749,9 +1727,6 @@ static int send_notification(struct rq *rq, int check_pred, int check_groups) int rc = 0; u64 group_load = 0, new_load = 0; - if (!sched_enable_hmp) - return 0; - if (check_pred) { u64 prev = rq->old_busy_time; u64 predicted = rq->hmp_stats.pred_demands_sum; @@ -2960,7 +2935,7 @@ void set_window_start(struct rq *rq) { static int sync_cpu_available; - if (rq->window_start || !sched_enable_hmp) + if (rq->window_start) return; if (!sync_cpu_available) { @@ -3539,7 +3514,7 @@ void fixup_busy_time(struct task_struct *p, int new_cpu) bool new_task; struct related_thread_group *grp; - if (!sched_enable_hmp || (!p->on_rq && p->state != TASK_WAKING)) + if (!p->on_rq && p->state != TASK_WAKING) return; if (exiting_task(p)) { @@ -4246,9 +4221,6 @@ static int register_sched_callback(void) { int ret; - if (!sched_enable_hmp) - return 0; - ret = cpufreq_register_notifier(¬ifier_policy_block, CPUFREQ_POLICY_NOTIFIER); diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 3fe00d6fa335..b72352bbd752 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -1406,6 +1406,7 @@ static void yield_task_rt(struct rq *rq) #ifdef CONFIG_SMP static int find_lowest_rq(struct task_struct *task); +#ifdef CONFIG_SCHED_HMP static int select_task_rq_rt_hmp(struct task_struct *p, int cpu, int sd_flag, int flags) { @@ -1419,6 +1420,7 @@ select_task_rq_rt_hmp(struct task_struct *p, int cpu, int sd_flag, int flags) return cpu; } +#endif static int select_task_rq_rt(struct task_struct *p, int cpu, int sd_flag, int flags) @@ -1426,8 +1428,9 @@ select_task_rq_rt(struct task_struct *p, int cpu, int sd_flag, int flags) struct task_struct *curr; struct rq *rq; - if (sched_enable_hmp) - return select_task_rq_rt_hmp(p, cpu, sd_flag, flags); +#ifdef CONFIG_SCHED_HMP + return select_task_rq_rt_hmp(p, cpu, sd_flag, flags); +#endif /* For anything but wake ups, just return the task_cpu */ if (sd_flag != SD_BALANCE_WAKE && sd_flag != SD_BALANCE_FORK) @@ -1796,14 +1799,6 @@ static int find_lowest_rq_hmp(struct task_struct *task) return best_cpu; } - -#else /* CONFIG_SCHED_HMP */ - -static int find_lowest_rq_hmp(struct task_struct *task) -{ - return -1; -} - #endif /* CONFIG_SCHED_HMP */ static int find_lowest_rq(struct task_struct *task) @@ -1813,8 +1808,9 @@ static int find_lowest_rq(struct task_struct *task) int this_cpu = smp_processor_id(); int cpu = task_cpu(task); - if (sched_enable_hmp) - return find_lowest_rq_hmp(task); +#ifdef CONFIG_SCHED_HMP + return find_lowest_rq_hmp(task); +#endif /* Make sure the mask is initialized first */ if (unlikely(!lowest_mask)) diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 3e2ef7b0df3e..a91f4cc1d8d3 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1085,7 +1085,6 @@ enum sched_boost_policy { extern struct mutex policy_mutex; extern unsigned int sched_ravg_window; extern unsigned int sched_disable_window_stats; -extern unsigned int sched_enable_hmp; extern unsigned int max_possible_freq; extern unsigned int min_max_freq; extern unsigned int pct_task_load(struct task_struct *p); @@ -1129,7 +1128,6 @@ extern void update_cluster_topology(void); extern void note_task_waking(struct task_struct *p, u64 wallclock); extern void set_task_last_switch_out(struct task_struct *p, u64 wallclock); extern void init_clusters(void); -extern int __init set_sched_enable_hmp(char *str); extern void reset_cpu_hmp_stats(int cpu, int reset_cra); extern unsigned int max_task_load(void); extern void sched_account_irqtime(int cpu, struct task_struct *curr, @@ -1259,7 +1257,7 @@ inc_cumulative_runnable_avg(struct hmp_sched_stats *stats, { u32 task_load; - if (!sched_enable_hmp || sched_disable_window_stats) + if (sched_disable_window_stats) return; task_load = sched_disable_window_stats ? 0 : p->ravg.demand; @@ -1274,7 +1272,7 @@ dec_cumulative_runnable_avg(struct hmp_sched_stats *stats, { u32 task_load; - if (!sched_enable_hmp || sched_disable_window_stats) + if (sched_disable_window_stats) return; task_load = sched_disable_window_stats ? 0 : p->ravg.demand; @@ -1292,7 +1290,7 @@ fixup_cumulative_runnable_avg(struct hmp_sched_stats *stats, struct task_struct *p, s64 task_load_delta, s64 pred_demand_delta) { - if (!sched_enable_hmp || sched_disable_window_stats) + if (sched_disable_window_stats) return; stats->cumulative_runnable_avg += task_load_delta; @@ -1661,7 +1659,6 @@ static inline int update_preferred_cluster(struct related_thread_group *grp, static inline void add_new_task_to_grp(struct task_struct *new) {} -#define sched_enable_hmp 0 #define PRED_DEMAND_DELTA (0) static inline void diff --git a/net/wireless/util.c b/net/wireless/util.c index ef394e8a42bc..00f5cededd38 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1080,7 +1080,7 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate) 58500000, 65000000, 78000000, - 0, + 86500000, }, { 13500000, 27000000, diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 328b4a43f09a..b73133885384 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -375,7 +375,8 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, * the elapsed time to detect xruns. */ jdelta = curr_jiffies - runtime->hw_ptr_jiffies; - if (jdelta < runtime->hw_ptr_buffer_jiffies / 2) + if ((jdelta < runtime->hw_ptr_buffer_jiffies / 2) || + (runtime->hw_ptr_buffer_jiffies <= 0)) goto no_delta_check; hdelta = jdelta - delta * HZ / runtime->rate; xrun_threshold = runtime->hw_ptr_buffer_jiffies / 2 + 1; diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c index cb201899b4b8..8454ebfc6216 100644 --- a/sound/soc/codecs/wcd-mbhc-v2.c +++ b/sound/soc/codecs/wcd-mbhc-v2.c @@ -1610,12 +1610,8 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc) WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, 0); wcd_mbhc_report_plug(mbhc, 0, SND_JACK_LINEOUT); } else if (mbhc->current_plug == MBHC_PLUG_TYPE_ANC_HEADPHONE) { - mbhc->mbhc_cb->irq_control(codec, - mbhc->intr_ids->mbhc_hs_rem_intr, - false); - mbhc->mbhc_cb->irq_control(codec, - mbhc->intr_ids->mbhc_hs_ins_intr, - false); + wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_REM, false); + wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_INS, false); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_DETECTION_TYPE, 0); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, 0); diff --git a/sound/soc/codecs/wcd934x/wcd934x-routing.h b/sound/soc/codecs/wcd934x/wcd934x-routing.h index 8ca4c07a3327..cd165af43eab 100644 --- a/sound/soc/codecs/wcd934x/wcd934x-routing.h +++ b/sound/soc/codecs/wcd934x/wcd934x-routing.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -914,9 +914,23 @@ const struct snd_soc_dapm_route tavil_audio_map[] = { {"ANC OUT EAR Enable", "Switch", "ADC MUX11"}, {"RX INT0 MIX2", NULL, "ANC OUT EAR Enable"}, + {"ANC OUT HPHL Enable", "Switch", "ADC MUX10"}, + {"ANC OUT HPHL Enable", "Switch", "ADC MUX11"}, + {"RX INT1 MIX2", NULL, "ANC OUT HPHL Enable"}, + + {"ANC OUT HPHR Enable", "Switch", "ADC MUX12"}, + {"ANC OUT HPHR Enable", "Switch", "ADC MUX13"}, + {"RX INT2 MIX2", NULL, "ANC OUT HPHR Enable"}, + {"ANC EAR PA", NULL, "RX INT0 DAC"}, {"ANC EAR", NULL, "ANC EAR PA"}, + {"ANC HPHL PA", NULL, "RX INT1 DAC"}, + {"ANC HPHL", NULL, "ANC HPHL PA"}, + + {"ANC HPHR PA", NULL, "RX INT2 DAC"}, + {"ANC HPHR", NULL, "ANC HPHR PA"}, + {"ANC OUT EAR SPKR Enable", "Switch", "ADC MUX10"}, {"ANC OUT EAR SPKR Enable", "Switch", "ADC MUX11"}, {"RX INT7 MIX2", NULL, "ANC OUT EAR SPKR Enable"}, diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c index c5d2b1ce8151..5b300a668489 100644 --- a/sound/soc/codecs/wcd934x/wcd934x.c +++ b/sound/soc/codecs/wcd934x/wcd934x.c @@ -176,6 +176,10 @@ enum { AUDIO_NOMINAL, HPH_PA_DELAY, CLSH_Z_CONFIG, + ANC_MIC_AMIC1, + ANC_MIC_AMIC2, + ANC_MIC_AMIC3, + ANC_MIC_AMIC4, }; enum { @@ -510,6 +514,7 @@ module_param(tx_unmute_delay, int, S_IRUGO | S_IWUSR | S_IWGRP); MODULE_PARM_DESC(tx_unmute_delay, "delay to unmute the tx path"); +static void tavil_codec_set_tx_hold(struct snd_soc_codec *, u16, bool); /* Hold instance to soundwire platform device */ struct tavil_swr_ctrl_data { @@ -998,14 +1003,30 @@ static int tavil_put_anc_func(struct snd_kcontrol *kcontrol, snd_soc_dapm_enable_pin(dapm, "ANC EAR PA"); snd_soc_dapm_enable_pin(dapm, "ANC EAR"); snd_soc_dapm_enable_pin(dapm, "ANC SPK1 PA"); + snd_soc_dapm_enable_pin(dapm, "ANC HPHL PA"); + snd_soc_dapm_enable_pin(dapm, "ANC HPHR PA"); + snd_soc_dapm_enable_pin(dapm, "ANC HPHL"); + snd_soc_dapm_enable_pin(dapm, "ANC HPHR"); snd_soc_dapm_disable_pin(dapm, "EAR PA"); snd_soc_dapm_disable_pin(dapm, "EAR"); + snd_soc_dapm_disable_pin(dapm, "HPHL PA"); + snd_soc_dapm_disable_pin(dapm, "HPHR PA"); + snd_soc_dapm_disable_pin(dapm, "HPHL"); + snd_soc_dapm_disable_pin(dapm, "HPHR"); } else { snd_soc_dapm_disable_pin(dapm, "ANC EAR PA"); snd_soc_dapm_disable_pin(dapm, "ANC EAR"); snd_soc_dapm_disable_pin(dapm, "ANC SPK1 PA"); + snd_soc_dapm_disable_pin(dapm, "ANC HPHL PA"); + snd_soc_dapm_disable_pin(dapm, "ANC HPHR PA"); + snd_soc_dapm_disable_pin(dapm, "ANC HPHL"); + snd_soc_dapm_disable_pin(dapm, "ANC HPHR"); snd_soc_dapm_enable_pin(dapm, "EAR PA"); snd_soc_dapm_enable_pin(dapm, "EAR"); + snd_soc_dapm_enable_pin(dapm, "HPHL"); + snd_soc_dapm_enable_pin(dapm, "HPHR"); + snd_soc_dapm_enable_pin(dapm, "HPHL PA"); + snd_soc_dapm_enable_pin(dapm, "HPHR PA"); } mutex_unlock(&tavil->codec_mutex); @@ -1122,16 +1143,56 @@ static int tavil_codec_enable_anc(struct snd_soc_dapm_widget *w, } /* Rate converter clk enable and set bypass mode */ - snd_soc_update_bits(codec, WCD934X_CDC_ANC0_RC_COMMON_CTL, - 0x05, 0x05); + if (!strcmp(w->name, "RX INT0 DAC") || + !strcmp(w->name, "RX INT1 DAC") || + !strcmp(w->name, "ANC SPK1 PA")) { + snd_soc_update_bits(codec, + WCD934X_CDC_ANC0_RC_COMMON_CTL, + 0x05, 0x05); + if (!strcmp(w->name, "RX INT1 DAC")) { + snd_soc_update_bits(codec, + WCD934X_CDC_ANC0_FIFO_COMMON_CTL, + 0x66, 0x66); + } + } else if (!strcmp(w->name, "RX INT2 DAC")) { + snd_soc_update_bits(codec, + WCD934X_CDC_ANC1_RC_COMMON_CTL, + 0x05, 0x05); + snd_soc_update_bits(codec, + WCD934X_CDC_ANC1_FIFO_COMMON_CTL, + 0x66, 0x66); + } + if (!strcmp(w->name, "RX INT1 DAC")) + snd_soc_update_bits(codec, + WCD934X_CDC_ANC0_CLK_RESET_CTL, 0x08, 0x08); + else if (!strcmp(w->name, "RX INT2 DAC")) + snd_soc_update_bits(codec, + WCD934X_CDC_ANC1_CLK_RESET_CTL, 0x08, 0x08); + if (!hwdep_cal) release_firmware(fw); break; + + case SND_SOC_DAPM_POST_PMU: + if (!strcmp(w->name, "ANC HPHL PA") || + !strcmp(w->name, "ANC HPHR PA")) { + /* Remove ANC Rx from reset */ + snd_soc_update_bits(codec, + WCD934X_CDC_ANC0_CLK_RESET_CTL, + 0x08, 0x00); + snd_soc_update_bits(codec, + WCD934X_CDC_ANC1_CLK_RESET_CTL, + 0x08, 0x00); + } + + break; + case SND_SOC_DAPM_POST_PMD: snd_soc_update_bits(codec, WCD934X_CDC_ANC0_RC_COMMON_CTL, 0x05, 0x00); if (!strcmp(w->name, "ANC EAR PA") || - !strcmp(w->name, "ANC SPK1 PA")) { + !strcmp(w->name, "ANC SPK1 PA") || + !strcmp(w->name, "ANC HPHL PA")) { snd_soc_update_bits(codec, WCD934X_CDC_ANC0_MODE_1_CTL, 0x30, 0x00); msleep(50); @@ -1146,6 +1207,21 @@ static int tavil_codec_enable_anc(struct snd_soc_dapm_widget *w, snd_soc_update_bits(codec, WCD934X_CDC_ANC0_CLK_RESET_CTL, 0x38, 0x00); + } else if (!strcmp(w->name, "ANC HPHR PA")) { + snd_soc_update_bits(codec, WCD934X_CDC_ANC1_MODE_1_CTL, + 0x30, 0x00); + msleep(50); + snd_soc_update_bits(codec, WCD934X_CDC_ANC1_MODE_1_CTL, + 0x01, 0x00); + snd_soc_update_bits(codec, + WCD934X_CDC_ANC1_CLK_RESET_CTL, + 0x38, 0x38); + snd_soc_update_bits(codec, + WCD934X_CDC_ANC1_CLK_RESET_CTL, + 0x07, 0x00); + snd_soc_update_bits(codec, + WCD934X_CDC_ANC1_CLK_RESET_CTL, + 0x38, 0x00); } break; } @@ -1893,6 +1969,18 @@ static void tavil_codec_override(struct snd_soc_codec *codec, int mode, } } +static void tavil_codec_clear_anc_tx_hold(struct tavil_priv *tavil) +{ + if (test_and_clear_bit(ANC_MIC_AMIC1, &tavil->status_mask)) + tavil_codec_set_tx_hold(tavil->codec, WCD934X_ANA_AMIC1, false); + if (test_and_clear_bit(ANC_MIC_AMIC2, &tavil->status_mask)) + tavil_codec_set_tx_hold(tavil->codec, WCD934X_ANA_AMIC2, false); + if (test_and_clear_bit(ANC_MIC_AMIC3, &tavil->status_mask)) + tavil_codec_set_tx_hold(tavil->codec, WCD934X_ANA_AMIC3, false); + if (test_and_clear_bit(ANC_MIC_AMIC4, &tavil->status_mask)) + tavil_codec_set_tx_hold(tavil->codec, WCD934X_ANA_AMIC4, false); +} + static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) @@ -1900,6 +1988,7 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec); struct tavil_dsd_config *dsd_conf = tavil->dsd_config; + int ret = 0; dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event); @@ -1908,6 +1997,11 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, if (TAVIL_IS_1_0(tavil->wcd9xxx)) snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL, 0x06, (0x03 << 1)); + + if ((!(strcmp(w->name, "ANC HPHR PA"))) && + (test_bit(HPH_PA_DELAY, &tavil->status_mask))) + snd_soc_update_bits(codec, WCD934X_ANA_HPH, 0xC0, 0xC0); + set_bit(HPH_PA_DELAY, &tavil->status_mask); if (dsd_conf && (snd_soc_read(codec, WCD934X_CDC_DSD1_PATH_CTL) & 0x01)) { @@ -1917,6 +2011,16 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, } break; case SND_SOC_DAPM_POST_PMU: + if ((!(strcmp(w->name, "ANC HPHR PA")))) { + if ((snd_soc_read(codec, WCD934X_ANA_HPH) & 0xC0) + != 0xC0) + /* + * If PA_EN is not set (potentially in ANC case) + * then do nothing for POST_PMU and let left + * channel handle everything. + */ + break; + } /* * 7ms sleep is required after PA is enabled as per * HW requirement. If compander is disabled, then @@ -1929,6 +2033,12 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, usleep_range(7000, 7100); clear_bit(HPH_PA_DELAY, &tavil->status_mask); } + if (tavil->anc_func) { + /* Clear Tx FE HOLD if both PAs are enabled */ + if ((snd_soc_read(tavil->codec, WCD934X_ANA_HPH) & + 0xC0) == 0xC0) + tavil_codec_clear_anc_tx_hold(tavil); + } snd_soc_update_bits(codec, WCD934X_HPH_R_TEST, 0x01, 0x01); @@ -1951,6 +2061,34 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, (snd_soc_read(codec, WCD934X_CDC_DSD1_PATH_CTL) & 0x01)) snd_soc_update_bits(codec, WCD934X_CDC_DSD1_CFG2, 0x04, 0x00); + if (!(strcmp(w->name, "ANC HPHR PA"))) { + pr_debug("%s:Do everything needed for left channel\n", + __func__); + /* Do everything needed for left channel */ + snd_soc_update_bits(codec, WCD934X_HPH_L_TEST, + 0x01, 0x01); + + /* Remove mute */ + snd_soc_update_bits(codec, WCD934X_CDC_RX1_RX_PATH_CTL, + 0x10, 0x00); + + /* Remove mix path mute if it is enabled */ + if ((snd_soc_read(codec, + WCD934X_CDC_RX1_RX_PATH_MIX_CTL)) & + 0x10) + snd_soc_update_bits(codec, + WCD934X_CDC_RX1_RX_PATH_MIX_CTL, + 0x10, 0x00); + + if (dsd_conf && (snd_soc_read(codec, + WCD934X_CDC_DSD0_PATH_CTL) & + 0x01)) + snd_soc_update_bits(codec, + WCD934X_CDC_DSD0_CFG2, + 0x04, 0x00); + /* Remove ANC Rx from reset */ + ret = tavil_codec_enable_anc(w, kcontrol, event); + } tavil_codec_override(codec, tavil->hph_mode, event); break; case SND_SOC_DAPM_PRE_PMD: @@ -1967,6 +2105,8 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, 0x10, 0x10); snd_soc_update_bits(codec, WCD934X_CDC_RX2_RX_PATH_MIX_CTL, 0x10, 0x10); + if (!(strcmp(w->name, "ANC HPHR PA"))) + snd_soc_update_bits(codec, WCD934X_ANA_HPH, 0x40, 0x00); break; case SND_SOC_DAPM_POST_PMD: /* @@ -1984,10 +2124,16 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, if (TAVIL_IS_1_0(tavil->wcd9xxx)) snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL, 0x06, 0x0); + if (!(strcmp(w->name, "ANC HPHR PA"))) { + ret = tavil_codec_enable_anc(w, kcontrol, event); + snd_soc_update_bits(codec, + WCD934X_CDC_RX2_RX_PATH_CFG0, + 0x10, 0x00); + } break; }; - return 0; + return ret; } static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, @@ -1997,6 +2143,7 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec); struct tavil_dsd_config *dsd_conf = tavil->dsd_config; + int ret = 0; dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event); @@ -2005,6 +2152,10 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, if (TAVIL_IS_1_0(tavil->wcd9xxx)) snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL, 0x06, (0x03 << 1)); + if ((!(strcmp(w->name, "ANC HPHL PA"))) && + (test_bit(HPH_PA_DELAY, &tavil->status_mask))) + snd_soc_update_bits(codec, WCD934X_ANA_HPH, + 0xC0, 0xC0); set_bit(HPH_PA_DELAY, &tavil->status_mask); if (dsd_conf && (snd_soc_read(codec, WCD934X_CDC_DSD0_PATH_CTL) & 0x01)) { @@ -2014,6 +2165,16 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, } break; case SND_SOC_DAPM_POST_PMU: + if (!(strcmp(w->name, "ANC HPHL PA"))) { + if ((snd_soc_read(codec, WCD934X_ANA_HPH) & 0xC0) + != 0xC0) + /* + * If PA_EN is not set (potentially in ANC + * case) then do nothing for POST_PMU and + * let right channel handle everything. + */ + break; + } /* * 7ms sleep is required after PA is enabled as per * HW requirement. If compander is disabled, then @@ -2026,6 +2187,13 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, usleep_range(7000, 7100); clear_bit(HPH_PA_DELAY, &tavil->status_mask); } + if (tavil->anc_func) { + /* Clear Tx FE HOLD if both PAs are enabled */ + if ((snd_soc_read(tavil->codec, WCD934X_ANA_HPH) & + 0xC0) == 0xC0) + tavil_codec_clear_anc_tx_hold(tavil); + } + snd_soc_update_bits(codec, WCD934X_HPH_L_TEST, 0x01, 0x01); /* Remove Mute on primary path */ snd_soc_update_bits(codec, WCD934X_CDC_RX1_RX_PATH_CTL, @@ -2046,6 +2214,33 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, (snd_soc_read(codec, WCD934X_CDC_DSD0_PATH_CTL) & 0x01)) snd_soc_update_bits(codec, WCD934X_CDC_DSD0_CFG2, 0x04, 0x00); + if (!(strcmp(w->name, "ANC HPHL PA"))) { + pr_debug("%s:Do everything needed for right channel\n", + __func__); + + /* Do everything needed for right channel */ + snd_soc_update_bits(codec, WCD934X_HPH_R_TEST, + 0x01, 0x01); + + /* Remove mute */ + snd_soc_update_bits(codec, WCD934X_CDC_RX2_RX_PATH_CTL, + 0x10, 0x00); + + /* Remove mix path mute if it is enabled */ + if ((snd_soc_read(codec, + WCD934X_CDC_RX2_RX_PATH_MIX_CTL)) & + 0x10) + snd_soc_update_bits(codec, + WCD934X_CDC_RX2_RX_PATH_MIX_CTL, + 0x10, 0x00); + if (dsd_conf && (snd_soc_read(codec, + WCD934X_CDC_DSD1_PATH_CTL) & 0x01)) + snd_soc_update_bits(codec, + WCD934X_CDC_DSD1_CFG2, + 0x04, 0x00); + /* Remove ANC Rx from reset */ + ret = tavil_codec_enable_anc(w, kcontrol, event); + } tavil_codec_override(codec, tavil->hph_mode, event); break; case SND_SOC_DAPM_PRE_PMD: @@ -2063,6 +2258,9 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, 0x10, 0x10); snd_soc_update_bits(codec, WCD934X_CDC_RX1_RX_PATH_MIX_CTL, 0x10, 0x10); + if (!(strcmp(w->name, "ANC HPHL PA"))) + snd_soc_update_bits(codec, WCD934X_ANA_HPH, + 0x80, 0x00); break; case SND_SOC_DAPM_POST_PMD: /* @@ -2080,10 +2278,15 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, if (TAVIL_IS_1_0(tavil->wcd9xxx)) snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL, 0x06, 0x0); + if (!(strcmp(w->name, "ANC HPHL PA"))) { + ret = tavil_codec_enable_anc(w, kcontrol, event); + snd_soc_update_bits(codec, + WCD934X_CDC_RX1_RX_PATH_CFG0, 0x10, 0x00); + } break; }; - return 0; + return ret; } static int tavil_codec_enable_lineout_pa(struct snd_soc_dapm_widget *w, @@ -2190,12 +2393,18 @@ static int tavil_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, int hph_mode = tavil->hph_mode; u8 dem_inp; struct tavil_dsd_config *dsd_conf = tavil->dsd_config; + int ret = 0; dev_dbg(codec->dev, "%s wname: %s event: %d hph_mode: %d\n", __func__, w->name, event, hph_mode); switch (event) { case SND_SOC_DAPM_PRE_PMU: + if (tavil->anc_func) { + ret = tavil_codec_enable_anc(w, kcontrol, event); + /* 40 msec delay is needed to avoid click and pop */ + msleep(40); + } /* Read DEM INP Select */ dem_inp = snd_soc_read(codec, WCD934X_CDC_RX2_RX_PATH_SEC0) & 0x03; @@ -2226,6 +2435,10 @@ static int tavil_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, WCD_CLSH_EVENT_PRE_DAC, WCD_CLSH_STATE_HPHR, hph_mode); + if (tavil->anc_func) + snd_soc_update_bits(codec, + WCD934X_CDC_RX2_RX_PATH_CFG0, + 0x10, 0x10); break; case SND_SOC_DAPM_POST_PMD: /* 1000us required as per HW requirement */ @@ -2269,6 +2482,11 @@ static int tavil_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: + if (tavil->anc_func) { + ret = tavil_codec_enable_anc(w, kcontrol, event); + /* 40 msec delay is needed to avoid click and pop */ + msleep(40); + } /* Read DEM INP Select */ dem_inp = snd_soc_read(codec, WCD934X_CDC_RX1_RX_PATH_SEC0) & 0x03; @@ -2300,6 +2518,11 @@ static int tavil_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, WCD_CLSH_STATE_HPHL, hph_mode); + if (tavil->anc_func) + snd_soc_update_bits(codec, + WCD934X_CDC_RX1_RX_PATH_CFG0, + 0x10, 0x10); + ret = tavil_mbhc_get_impedance(tavil->mbhc, &impedl, &impedr); if (!ret) { @@ -3184,6 +3407,15 @@ int tavil_codec_enable_interp_clk(struct snd_soc_codec *codec, } EXPORT_SYMBOL(tavil_codec_enable_interp_clk); +static int tavil_anc_out_switch_cb(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + + tavil_codec_enable_interp_clk(codec, event, w->shift); + + return 0; +} static int tavil_codec_set_idle_detect_thr(struct snd_soc_codec *codec, int interp, int path_type) { @@ -3638,8 +3870,8 @@ static int tavil_codec_tx_adc_cfg(struct snd_soc_dapm_widget *w, { int adc_mux_n = w->shift; struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec); int amic_n; - u16 amic_reg; dev_dbg(codec->dev, "%s: event: %d\n", __func__, event); @@ -3647,8 +3879,13 @@ static int tavil_codec_tx_adc_cfg(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMU: amic_n = tavil_codec_find_amic_input(codec, adc_mux_n); if (amic_n) { - amic_reg = WCD934X_ANA_AMIC1 + amic_n - 1; - tavil_codec_set_tx_hold(codec, amic_reg, false); + /* + * Prevent ANC Rx pop by leaving Tx FE in HOLD + * state until PA is up. Track AMIC being used + * so we can release the HOLD later. + */ + set_bit(ANC_MIC_AMIC1 + amic_n - 1, + &tavil->status_mask); } break; default: @@ -6471,6 +6708,12 @@ static const struct snd_kcontrol_new anc_ear_spkr_switch = static const struct snd_kcontrol_new anc_spkr_pa_switch = SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0); +static const struct snd_kcontrol_new anc_hphl_pa_switch = + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0); + +static const struct snd_kcontrol_new anc_hphr_pa_switch = + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0); + static const struct snd_kcontrol_new mad_cpe1_switch = SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0); @@ -7110,6 +7353,14 @@ static const struct snd_soc_dapm_widget tavil_dapm_widgets[] = { SND_SOC_DAPM_PGA_E("ANC SPK1 PA", SND_SOC_NOPM, 0, 0, NULL, 0, tavil_codec_enable_spkr_anc, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PGA_E("ANC HPHL PA", SND_SOC_NOPM, 0, 0, NULL, 0, + tavil_codec_enable_hphl_pa, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PGA_E("ANC HPHR PA", SND_SOC_NOPM, 0, 0, NULL, 0, + tavil_codec_enable_hphr_pa, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_OUTPUT("EAR"), SND_SOC_DAPM_OUTPUT("HPHL"), @@ -7119,6 +7370,8 @@ static const struct snd_soc_dapm_widget tavil_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("SPK1 OUT"), SND_SOC_DAPM_OUTPUT("SPK2 OUT"), SND_SOC_DAPM_OUTPUT("ANC EAR"), + SND_SOC_DAPM_OUTPUT("ANC HPHL"), + SND_SOC_DAPM_OUTPUT("ANC HPHR"), SND_SOC_DAPM_SWITCH("ANC OUT EAR Enable", SND_SOC_NOPM, 0, 0, &anc_ear_switch), @@ -7127,6 +7380,13 @@ static const struct snd_soc_dapm_widget tavil_dapm_widgets[] = { SND_SOC_DAPM_SWITCH("ANC SPKR PA Enable", SND_SOC_NOPM, 0, 0, &anc_spkr_pa_switch), + SND_SOC_DAPM_SWITCH_E("ANC OUT HPHL Enable", SND_SOC_NOPM, INTERP_HPHL, + 0, &anc_hphl_pa_switch, tavil_anc_out_switch_cb, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_SWITCH_E("ANC OUT HPHR Enable", SND_SOC_NOPM, INTERP_HPHR, + 0, &anc_hphr_pa_switch, tavil_anc_out_switch_cb, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0, tavil_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), @@ -9030,6 +9290,10 @@ static int tavil_soc_codec_probe(struct snd_soc_codec *codec) mutex_lock(&tavil->codec_mutex); snd_soc_dapm_disable_pin(dapm, "ANC EAR PA"); snd_soc_dapm_disable_pin(dapm, "ANC EAR"); + snd_soc_dapm_disable_pin(dapm, "ANC HPHL PA"); + snd_soc_dapm_disable_pin(dapm, "ANC HPHR PA"); + snd_soc_dapm_disable_pin(dapm, "ANC HPHL"); + snd_soc_dapm_disable_pin(dapm, "ANC HPHR"); snd_soc_dapm_enable_pin(dapm, "ANC SPK1 PA"); mutex_unlock(&tavil->codec_mutex); diff --git a/sound/soc/codecs/wcd_cpe_core.c b/sound/soc/codecs/wcd_cpe_core.c index 2088698392de..2082c356203d 100644 --- a/sound/soc/codecs/wcd_cpe_core.c +++ b/sound/soc/codecs/wcd_cpe_core.c @@ -3029,7 +3029,7 @@ err_ret: static int wcd_cpe_set_one_param(void *core_handle, struct cpe_lsm_session *session, struct lsm_params_info *p_info, - void *data, enum LSM_PARAM_TYPE param_type) + void *data, uint32_t param_type) { struct wcd_cpe_core *core = core_handle; int rc = 0; @@ -3044,25 +3044,9 @@ static int wcd_cpe_set_one_param(void *core_handle, rc = wcd_cpe_send_param_epd_thres(core, session, data, &ids); break; - case LSM_OPERATION_MODE: { - struct cpe_lsm_ids connectport_ids; - - rc = wcd_cpe_send_param_opmode(core, session, - data, &ids); - if (rc) - break; - - connectport_ids.module_id = LSM_MODULE_ID_FRAMEWORK; - connectport_ids.param_id = LSM_PARAM_ID_CONNECT_TO_PORT; - - rc = wcd_cpe_send_param_connectport(core, session, NULL, - &connectport_ids, CPE_AFE_PORT_1_TX); - if (rc) - dev_err(core->dev, - "%s: send_param_connectport failed, err %d\n", - __func__, rc); + case LSM_OPERATION_MODE: + rc = wcd_cpe_send_param_opmode(core, session, data, &ids); break; - } case LSM_GAIN: rc = wcd_cpe_send_param_gain(core, session, data, &ids); break; @@ -3081,13 +3065,13 @@ static int wcd_cpe_set_one_param(void *core_handle, break; default: pr_err("%s: wrong param_type 0x%x\n", - __func__, p_info->param_type); + __func__, param_type); } if (rc) dev_err(core->dev, "%s: send_param(%d) failed, err %d\n", - __func__, p_info->param_type, rc); + __func__, param_type, rc); return rc; } diff --git a/sound/soc/msm/msm-cpe-lsm.c b/sound/soc/msm/msm-cpe-lsm.c index ffc6119e543d..b2008d6da2a1 100644 --- a/sound/soc/msm/msm-cpe-lsm.c +++ b/sound/soc/msm/msm-cpe-lsm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, 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 @@ -1049,7 +1049,6 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, struct cpe_lsm_lab *lab_d = &lsm_d->lab; struct snd_dma_buffer *dma_buf = &substream->dma_buffer; struct msm_slim_dma_data *dma_data = NULL; - struct snd_lsm_event_status *user; struct snd_lsm_detection_params det_params; int rc = 0; @@ -1318,11 +1317,20 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, break; case SNDRV_LSM_EVENT_STATUS: + case SNDRV_LSM_EVENT_STATUS_V3: { + struct snd_lsm_event_status *user; + struct snd_lsm_event_status_v3 *user_v3; + dev_dbg(rtd->dev, "%s: %s\n", - __func__, "SNDRV_LSM_EVENT_STATUS"); - - user = arg; + __func__, "SNDRV_LSM_EVENT_STATUS(_V3)"); + if (!arg) { + dev_err(rtd->dev, + "%s: Invalid argument to ioctl %s\n", + __func__, + "SNDRV_LSM_EVENT_STATUS(_V3)"); + return -EINVAL; + } /* * Release the api lock before wait to allow @@ -1343,31 +1351,62 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, if (atomic_read(&lsm_d->event_avail) == 1) { rc = 0; atomic_set(&lsm_d->event_avail, 0); - if (lsm_d->ev_det_pld_size > - user->payload_size) { - dev_err(rtd->dev, - "%s: avail pld_bytes = %u, needed = %u\n", - __func__, - user->payload_size, - lsm_d->ev_det_pld_size); - return -EINVAL; - } - - user->status = lsm_d->ev_det_status; - user->payload_size = lsm_d->ev_det_pld_size; - - memcpy(user->payload, - lsm_d->ev_det_payload, - lsm_d->ev_det_pld_size); + if (cmd == SNDRV_LSM_EVENT_STATUS) { + user = arg; + if (lsm_d->ev_det_pld_size > + user->payload_size) { + dev_err(rtd->dev, + "%s: avail pld_bytes = %u, needed = %u\n", + __func__, + user->payload_size, + lsm_d->ev_det_pld_size); + return -EINVAL; + } + + user->status = lsm_d->ev_det_status; + user->payload_size = + lsm_d->ev_det_pld_size; + memcpy(user->payload, + lsm_d->ev_det_payload, + lsm_d->ev_det_pld_size); + } else { + user_v3 = arg; + if (lsm_d->ev_det_pld_size > + user_v3->payload_size) { + dev_err(rtd->dev, + "%s: avail pld_bytes = %u, needed = %u\n", + __func__, + user_v3->payload_size, + lsm_d->ev_det_pld_size); + return -EINVAL; + } + /* event status timestamp not supported + * on CPE mode. Set msw and lsw to 0. + */ + user_v3->timestamp_lsw = 0; + user_v3->timestamp_msw = 0; + user_v3->status = lsm_d->ev_det_status; + user_v3->payload_size = + lsm_d->ev_det_pld_size; + memcpy(user_v3->payload, + lsm_d->ev_det_payload, + lsm_d->ev_det_pld_size); + } } else if (atomic_read(&lsm_d->event_stop) == 1) { dev_dbg(rtd->dev, "%s: wait_aborted\n", __func__); - user->payload_size = 0; + if (cmd == SNDRV_LSM_EVENT_STATUS) { + user = arg; + user->payload_size = 0; + } else { + user_v3 = arg; + user_v3->payload_size = 0; + } rc = 0; } } - + } break; case SNDRV_LSM_ABORT_EVENT: @@ -1499,6 +1538,20 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, } break; + case SNDRV_LSM_SET_PORT: { + u32 port_id = cpe->input_port_id; + + dev_dbg(rtd->dev, "%s: %s\n", __func__, "SNDRV_LSM_SET_PORT"); + rc = lsm_ops->lsm_set_port(cpe->core_handle, session, &port_id); + if (rc) { + dev_err(rtd->dev, + "%s: lsm_set_port failed, err = %d\n", + __func__, rc); + return rc; + } + } + break; + default: dev_dbg(rtd->dev, "%s: Default snd_lib_ioctl cmd 0x%x\n", @@ -1510,7 +1563,7 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, } static int msm_cpe_lsm_lab_start(struct snd_pcm_substream *substream, - struct snd_lsm_event_status *event_status) + u16 event_det_status) { struct snd_soc_pcm_runtime *rtd; struct cpe_lsm_data *lsm_d = NULL; @@ -1563,7 +1616,7 @@ static int msm_cpe_lsm_lab_start(struct snd_pcm_substream *substream, reinit_completion(&lab_d->thread_complete); if (session->lab_enable && - event_status->status == + event_det_status == LSM_VOICE_WAKEUP_STATUS_DETECTED) { out_port = &session->afe_out_port_cfg; out_port->port_id = session->afe_out_port_id; @@ -2167,7 +2220,60 @@ static int msm_cpe_lsm_ioctl(struct snd_pcm_substream *substream, goto done; } - msm_cpe_lsm_lab_start(substream, event_status); + msm_cpe_lsm_lab_start(substream, event_status->status); + msm_cpe_process_event_status_done(lsm_d); + kfree(event_status); + } + break; + case SNDRV_LSM_EVENT_STATUS_V3: { + struct snd_lsm_event_status_v3 u_event_status; + struct snd_lsm_event_status_v3 *event_status = NULL; + int u_pld_size = 0; + + if (copy_from_user(&u_event_status, (void *)arg, + sizeof(struct snd_lsm_event_status_v3))) { + dev_err(rtd->dev, + "%s: event status copy from user failed, size %zd\n", + __func__, + sizeof(struct snd_lsm_event_status_v3)); + err = -EFAULT; + goto done; + } + + if (u_event_status.payload_size > + LISTEN_MAX_STATUS_PAYLOAD_SIZE) { + dev_err(rtd->dev, + "%s: payload_size %d is invalid, max allowed = %d\n", + __func__, u_event_status.payload_size, + LISTEN_MAX_STATUS_PAYLOAD_SIZE); + err = -EINVAL; + goto done; + } + + u_pld_size = sizeof(struct snd_lsm_event_status_v3) + + u_event_status.payload_size; + + event_status = kzalloc(u_pld_size, GFP_KERNEL); + if (!event_status) { + err = -ENOMEM; + goto done; + } else { + event_status->payload_size = + u_event_status.payload_size; + err = msm_cpe_lsm_ioctl_shared(substream, + cmd, event_status); + } + + if (!err && copy_to_user(arg, event_status, u_pld_size)) { + dev_err(rtd->dev, + "%s: copy to user failed\n", + __func__); + kfree(event_status); + err = -EFAULT; + goto done; + } + + msm_cpe_lsm_lab_start(substream, event_status->status); msm_cpe_process_event_status_done(lsm_d); kfree(event_status); } @@ -2297,7 +2403,7 @@ struct lsm_params_info_32 { u32 param_id; u32 param_size; compat_uptr_t param_data; - enum LSM_PARAM_TYPE param_type; + uint32_t param_type; }; struct snd_lsm_module_params_32 { @@ -2480,7 +2586,97 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream, goto done; } - msm_cpe_lsm_lab_start(substream, event_status); + msm_cpe_lsm_lab_start(substream, event_status->status); + msm_cpe_process_event_status_done(lsm_d); + kfree(event_status); + kfree(udata_32); + } + break; + case SNDRV_LSM_EVENT_STATUS_V3: { + struct snd_lsm_event_status_v3 *event_status = NULL; + struct snd_lsm_event_status_v3 u_event_status32; + struct snd_lsm_event_status_v3 *udata_32 = NULL; + int u_pld_size = 0; + + dev_dbg(rtd->dev, + "%s: ioctl %s\n", __func__, + "SNDRV_LSM_EVENT_STATUS_V3_32"); + + if (copy_from_user(&u_event_status32, (void *)arg, + sizeof(struct snd_lsm_event_status_v3))) { + dev_err(rtd->dev, + "%s: event status copy from user failed, size %zd\n", + __func__, + sizeof(struct snd_lsm_event_status_v3)); + err = -EFAULT; + goto done; + } + + if (u_event_status32.payload_size > + LISTEN_MAX_STATUS_PAYLOAD_SIZE) { + dev_err(rtd->dev, + "%s: payload_size %d is invalid, max allowed = %d\n", + __func__, u_event_status32.payload_size, + LISTEN_MAX_STATUS_PAYLOAD_SIZE); + err = -EINVAL; + goto done; + } + + u_pld_size = sizeof(struct snd_lsm_event_status_v3) + + u_event_status32.payload_size; + event_status = kzalloc(u_pld_size, GFP_KERNEL); + if (!event_status) { + dev_err(rtd->dev, + "%s: No memory for event status\n", + __func__); + err = -ENOMEM; + goto done; + } else { + event_status->payload_size = + u_event_status32.payload_size; + err = msm_cpe_lsm_ioctl_shared(substream, + cmd, event_status); + if (err) + dev_err(rtd->dev, + "%s: %s failed, error = %d\n", + __func__, + "SNDRV_LSM_EVENT_STATUS_V3_32", + err); + } + + if (!err) { + udata_32 = kzalloc(u_pld_size, GFP_KERNEL); + if (!udata_32) { + dev_err(rtd->dev, + "%s: nomem for udata\n", + __func__); + err = -EFAULT; + } else { + udata_32->timestamp_lsw = + event_status->timestamp_lsw; + udata_32->timestamp_msw = + event_status->timestamp_msw; + udata_32->status = event_status->status; + udata_32->payload_size = + event_status->payload_size; + memcpy(udata_32->payload, + event_status->payload, + u_pld_size); + } + } + + if (!err && copy_to_user(arg, udata_32, + u_pld_size)) { + dev_err(rtd->dev, + "%s: copy to user failed\n", + __func__); + kfree(event_status); + kfree(udata_32); + err = -EFAULT; + goto done; + } + + msm_cpe_lsm_lab_start(substream, event_status->status); msm_cpe_process_event_status_done(lsm_d); kfree(event_status); kfree(udata_32); diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c index 6c1897340e74..44a6a245c7a2 100644 --- a/sound/soc/msm/msm-dai-fe.c +++ b/sound/soc/msm/msm-dai-fe.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2203,12 +2203,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .capture = { .stream_name = "Listen 1 Audio Service Capture", .aif_name = "LSM1_UL_HL", - .rates = SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = (SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, - .channels_max = 1, + .channels_max = 4, .rate_min = 16000, - .rate_max = 16000, + .rate_max = 48000, }, .ops = &msm_fe_dai_ops, .name = "LSM1", @@ -2218,12 +2220,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .capture = { .stream_name = "Listen 2 Audio Service Capture", .aif_name = "LSM2_UL_HL", - .rates = SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = (SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, - .channels_max = 1, + .channels_max = 4, .rate_min = 16000, - .rate_max = 16000, + .rate_max = 48000, }, .ops = &msm_fe_dai_ops, .name = "LSM2", @@ -2233,12 +2237,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .capture = { .stream_name = "Listen 3 Audio Service Capture", .aif_name = "LSM3_UL_HL", - .rates = SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = (SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, - .channels_max = 1, + .channels_max = 4, .rate_min = 16000, - .rate_max = 16000, + .rate_max = 48000, }, .ops = &msm_fe_dai_ops, .name = "LSM3", @@ -2248,12 +2254,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .capture = { .stream_name = "Listen 4 Audio Service Capture", .aif_name = "LSM4_UL_HL", - .rates = SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = (SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, - .channels_max = 1, + .channels_max = 4, .rate_min = 16000, - .rate_max = 16000, + .rate_max = 48000, }, .ops = &msm_fe_dai_ops, .name = "LSM4", @@ -2263,12 +2271,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .capture = { .stream_name = "Listen 5 Audio Service Capture", .aif_name = "LSM5_UL_HL", - .rates = SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = (SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, - .channels_max = 1, + .channels_max = 4, .rate_min = 16000, - .rate_max = 16000, + .rate_max = 48000, }, .ops = &msm_fe_dai_ops, .name = "LSM5", @@ -2278,12 +2288,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .capture = { .stream_name = "Listen 6 Audio Service Capture", .aif_name = "LSM6_UL_HL", - .rates = SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = (SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, - .channels_max = 1, + .channels_max = 4, .rate_min = 16000, - .rate_max = 16000, + .rate_max = 48000, }, .ops = &msm_fe_dai_ops, .name = "LSM6", @@ -2293,12 +2305,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .capture = { .stream_name = "Listen 7 Audio Service Capture", .aif_name = "LSM7_UL_HL", - .rates = SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = (SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, - .channels_max = 1, + .channels_max = 4, .rate_min = 16000, - .rate_max = 16000, + .rate_max = 48000, }, .ops = &msm_fe_dai_ops, .name = "LSM7", @@ -2308,12 +2322,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .capture = { .stream_name = "Listen 8 Audio Service Capture", .aif_name = "LSM8_UL_HL", - .rates = SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = (SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, - .channels_max = 1, + .channels_max = 4, .rate_min = 16000, - .rate_max = 16000, + .rate_max = 48000, }, .ops = &msm_fe_dai_ops, .name = "LSM8", diff --git a/sound/soc/msm/msm8998.c b/sound/soc/msm/msm8998.c index 557c7946506a..391640d53d56 100644 --- a/sound/soc/msm/msm8998.c +++ b/sound/soc/msm/msm8998.c @@ -3383,12 +3383,12 @@ static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_ignore_suspend(dapm, "HPHR"); snd_soc_dapm_ignore_suspend(dapm, "AIF4 VI"); snd_soc_dapm_ignore_suspend(dapm, "VIINPUT"); + snd_soc_dapm_ignore_suspend(dapm, "ANC HPHL"); + snd_soc_dapm_ignore_suspend(dapm, "ANC HPHR"); if (!strcmp(dev_name(codec_dai->dev), "tasha_codec")) { snd_soc_dapm_ignore_suspend(dapm, "LINEOUT3"); snd_soc_dapm_ignore_suspend(dapm, "LINEOUT4"); - snd_soc_dapm_ignore_suspend(dapm, "ANC HPHL"); - snd_soc_dapm_ignore_suspend(dapm, "ANC HPHR"); snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT1"); snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT2"); } diff --git a/sound/soc/msm/qdsp6v2/audio_cal_utils.c b/sound/soc/msm/qdsp6v2/audio_cal_utils.c index 75af648baef3..b54cde4ef0c3 100644 --- a/sound/soc/msm/qdsp6v2/audio_cal_utils.c +++ b/sound/soc/msm/qdsp6v2/audio_cal_utils.c @@ -607,7 +607,6 @@ static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type, } INIT_LIST_HEAD(&cal_block->list); - list_add_tail(&cal_block->list, &cal_type->cal_blocks); cal_block->map_data.ion_map_handle = basic_cal->cal_data.mem_handle; if (basic_cal->cal_data.mem_handle > 0) { @@ -639,6 +638,7 @@ static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type, goto err; } cal_block->buffer_number = basic_cal->cal_hdr.buffer_number; + list_add_tail(&cal_block->list, &cal_type->cal_blocks); pr_debug("%s: created block for cal type %d, buf num %d, map handle %d, map size %zd paddr 0x%pK!\n", __func__, cal_type->info.reg.cal_type, cal_block->buffer_number, @@ -648,6 +648,8 @@ static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type, done: return cal_block; err: + kfree(cal_block->cal_info); + kfree(cal_block->client_info); kfree(cal_block); cal_block = NULL; return cal_block; diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c index efb6644e551f..55ca659567f5 100644 --- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c +++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, 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 @@ -35,7 +35,7 @@ #define CAPTURE_MIN_NUM_PERIODS 2 #define CAPTURE_MAX_NUM_PERIODS 8 -#define CAPTURE_MAX_PERIOD_SIZE 4096 +#define CAPTURE_MAX_PERIOD_SIZE 61440 #define CAPTURE_MIN_PERIOD_SIZE 320 #define LISTEN_MAX_STATUS_PAYLOAD_SIZE 256 @@ -47,12 +47,14 @@ static struct snd_pcm_hardware msm_pcm_hardware_capture = { SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_16000, + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), + .rates = (SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), .rate_min = 16000, - .rate_max = 16000, + .rate_max = 48000, .channels_min = 1, - .channels_max = 1, + .channels_max = 4, .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE, .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE, @@ -64,7 +66,7 @@ static struct snd_pcm_hardware msm_pcm_hardware_capture = { /* Conventional and unconventional sample rate supported */ static unsigned int supported_sample_rates[] = { - 16000, + 16000, 48000, }; static struct snd_pcm_hw_constraint_list constraints_sample_rates = { @@ -76,7 +78,7 @@ static struct snd_pcm_hw_constraint_list constraints_sample_rates = { struct lsm_priv { struct snd_pcm_substream *substream; struct lsm_client *lsm_client; - struct snd_lsm_event_status *event_status; + struct snd_lsm_event_status_v3 *event_status; spinlock_t event_lock; wait_queue_head_t event_wait; unsigned long event_avail; @@ -88,6 +90,11 @@ struct lsm_priv { int dma_write; }; +enum { /* lsm session states */ + IDLE = 0, + RUNNING, +}; + static int msm_lsm_queue_lab_buffer(struct lsm_priv *prtd, int i) { int rc = 0; @@ -196,6 +203,8 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token, uint16_t status = 0; uint16_t payload_size = 0; uint16_t index = 0; + uint32_t event_ts_lsw = 0; + uint32_t event_ts_msw = 0; if (!substream || !substream->private_data) { pr_err("%s: Invalid %s\n", __func__, @@ -269,24 +278,44 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token, "%s: event detect status = %d payload size = %d\n", __func__, status , payload_size); break; + + case LSM_SESSION_EVENT_DETECTION_STATUS_V3: + event_ts_lsw = ((uint32_t *)payload)[0]; + event_ts_msw = ((uint32_t *)payload)[1]; + status = (uint16_t)((uint8_t *)payload)[8]; + payload_size = (uint16_t)((uint8_t *)payload)[9]; + index = 10; + dev_dbg(rtd->dev, + "%s: ts_msw = %u, ts_lsw = %u, event detect status = %d payload size = %d\n", + __func__, event_ts_msw, event_ts_lsw, status, + payload_size); + break; + default: break; } if (opcode == LSM_SESSION_EVENT_DETECTION_STATUS || - opcode == LSM_SESSION_EVENT_DETECTION_STATUS_V2) { + opcode == LSM_SESSION_EVENT_DETECTION_STATUS_V2 || + opcode == LSM_SESSION_EVENT_DETECTION_STATUS_V3) { spin_lock_irqsave(&prtd->event_lock, flags); prtd->event_status = krealloc(prtd->event_status, - sizeof(struct snd_lsm_event_status) + + sizeof(struct snd_lsm_event_status_v3) + payload_size, GFP_ATOMIC); if (!prtd->event_status) { dev_err(rtd->dev, "%s: no memory for event status\n", __func__); return; } - + /* + * event status timestamp will be non-zero and valid if + * opcode is LSM_SESSION_EVENT_DETECTION_STATUS_V3 + */ + prtd->event_status->timestamp_lsw = event_ts_lsw; + prtd->event_status->timestamp_msw = event_ts_msw; prtd->event_status->status = status; prtd->event_status->payload_size = payload_size; + if (likely(prtd->event_status)) { memcpy(prtd->event_status->payload, &((uint8_t *)payload)[index], @@ -641,6 +670,54 @@ err_ret: return rc; } +static int msm_lsm_set_poll_enable(struct snd_pcm_substream *substream, + struct lsm_params_info *p_info) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct lsm_priv *prtd = runtime->private_data; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_lsm_poll_enable poll_enable; + int rc = 0; + + if (p_info->param_size != sizeof(poll_enable)) { + dev_err(rtd->dev, + "%s: Invalid param_size %d\n", + __func__, p_info->param_size); + rc = -EINVAL; + goto done; + } + + if (copy_from_user(&poll_enable, p_info->param_data, + sizeof(poll_enable))) { + dev_err(rtd->dev, + "%s: copy_from_user failed, size = %zd\n", + __func__, sizeof(poll_enable)); + rc = -EFAULT; + goto done; + } + + if (prtd->lsm_client->poll_enable == poll_enable.poll_en) { + dev_dbg(rtd->dev, + "%s: Polling for session %d already %s\n", + __func__, prtd->lsm_client->session, + (poll_enable.poll_en ? "enabled" : "disabled")); + rc = 0; + goto done; + } + + rc = q6lsm_set_one_param(prtd->lsm_client, p_info, + &poll_enable, LSM_POLLING_ENABLE); + if (!rc) { + prtd->lsm_client->poll_enable = poll_enable.poll_en; + } else { + dev_err(rtd->dev, + "%s: Failed to set poll enable, err = %d\n", + __func__, rc); + } +done: + return rc; +} + static int msm_lsm_process_params(struct snd_pcm_substream *substream, struct snd_lsm_module_params *p_data, void *params) @@ -681,6 +758,9 @@ static int msm_lsm_process_params(struct snd_pcm_substream *substream, case LSM_CUSTOM_PARAMS: rc = msm_lsm_set_custom(substream, p_info); break; + case LSM_POLLING_ENABLE: + rc = msm_lsm_set_poll_enable(substream, p_info); + break; default: dev_err(rtd->dev, "%s: Invalid param_type %d\n", @@ -710,10 +790,8 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, struct snd_lsm_session_data session_data; int rc = 0; int xchg = 0; - u32 size = 0; struct snd_pcm_runtime *runtime; struct lsm_priv *prtd; - struct snd_lsm_event_status *user = arg; struct snd_lsm_detection_params det_params; uint8_t *confidence_level = NULL; @@ -870,6 +948,10 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, break; case SNDRV_LSM_EVENT_STATUS: + case SNDRV_LSM_EVENT_STATUS_V3: { + uint32_t ts_lsw, ts_msw; + uint16_t status = 0, payload_size = 0; + dev_dbg(rtd->dev, "%s: Get event status\n", __func__); atomic_set(&prtd->event_wait_stop, 0); rc = wait_event_freezable(prtd->event_wait, @@ -882,9 +964,12 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, dev_dbg(rtd->dev, "%s: New event available %ld\n", __func__, prtd->event_avail); spin_lock_irqsave(&prtd->event_lock, flags); + if (prtd->event_status) { - size = sizeof(*(prtd->event_status)) + - prtd->event_status->payload_size; + payload_size = prtd->event_status->payload_size; + ts_lsw = prtd->event_status->timestamp_lsw; + ts_msw = prtd->event_status->timestamp_msw; + status = prtd->event_status->status; spin_unlock_irqrestore(&prtd->event_lock, flags); } else { @@ -896,15 +981,43 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, __func__); break; } - if (user->payload_size < - prtd->event_status->payload_size) { - dev_dbg(rtd->dev, - "%s: provided %d bytes isn't enough, needs %d bytes\n", - __func__, user->payload_size, - prtd->event_status->payload_size); - rc = -ENOMEM; + + if (cmd == SNDRV_LSM_EVENT_STATUS) { + struct snd_lsm_event_status *user = arg; + + if (user->payload_size < payload_size) { + dev_dbg(rtd->dev, + "%s: provided %d bytes isn't enough, needs %d bytes\n", + __func__, user->payload_size, + payload_size); + rc = -ENOMEM; + } else { + user->status = status; + user->payload_size = payload_size; + memcpy(user->payload, + prtd->event_status->payload, + payload_size); + } } else { - memcpy(user, prtd->event_status, size); + struct snd_lsm_event_status_v3 *user_v3 = arg; + + if (user_v3->payload_size < payload_size) { + dev_dbg(rtd->dev, + "%s: provided %d bytes isn't enough, needs %d bytes\n", + __func__, user_v3->payload_size, + payload_size); + rc = -ENOMEM; + } else { + user_v3->timestamp_lsw = ts_lsw; + user_v3->timestamp_msw = ts_msw; + user_v3->status = status; + user_v3->payload_size = payload_size; + memcpy(user_v3->payload, + prtd->event_status->payload, + payload_size); + } + } + if (!rc) { if (prtd->lsm_client->lab_enable && !prtd->lsm_client->lab_started && prtd->event_status->status == @@ -929,6 +1042,7 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, rc = 0; } break; + } case SNDRV_LSM_ABORT_EVENT: dev_dbg(rtd->dev, "%s: Aborting event status wait\n", @@ -1035,6 +1149,43 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, prtd->lsm_client->lab_started = false; } break; + + case SNDRV_LSM_SET_PORT: + dev_dbg(rtd->dev, "%s: set LSM port\n", __func__); + rc = q6lsm_set_port_connected(prtd->lsm_client); + break; + + case SNDRV_LSM_SET_FWK_MODE_CONFIG: { + u32 *mode = NULL; + + if (!arg) { + dev_err(rtd->dev, + "%s: Invalid param arg for ioctl %s session %d\n", + __func__, "SNDRV_LSM_SET_FWK_MODE_CONFIG", + prtd->lsm_client->session); + rc = -EINVAL; + break; + } + mode = (u32 *)arg; + if (prtd->lsm_client->event_mode == *mode) { + dev_dbg(rtd->dev, + "%s: mode for %d already set to %d\n", + __func__, prtd->lsm_client->session, *mode); + rc = 0; + } else { + dev_dbg(rtd->dev, "%s: Event mode = %d\n", + __func__, *mode); + rc = q6lsm_set_fwk_mode_cfg(prtd->lsm_client, *mode); + if (!rc) + prtd->lsm_client->event_mode = *mode; + else + dev_err(rtd->dev, + "%s: set event mode failed %d\n", + __func__, rc); + } + break; + } + default: dev_dbg(rtd->dev, "%s: Falling into default snd_lib_ioctl cmd 0x%x\n", @@ -1053,6 +1204,21 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, return rc; } #ifdef CONFIG_COMPAT + +struct snd_lsm_event_status32 { + u16 status; + u16 payload_size; + u8 payload[0]; +}; + +struct snd_lsm_event_status_v3_32 { + u32 timestamp_lsw; + u32 timestamp_msw; + u16 status; + u16 payload_size; + u8 payload[0]; +}; + struct snd_lsm_sound_model_v2_32 { compat_uptr_t data; compat_uptr_t confidence_level; @@ -1074,7 +1240,7 @@ struct lsm_params_info_32 { u32 param_id; u32 param_size; compat_uptr_t param_data; - enum LSM_PARAM_TYPE param_type; + uint32_t param_type; }; struct snd_lsm_module_params_32 { @@ -1090,6 +1256,8 @@ enum { _IOW('U', 0x0A, struct snd_lsm_detection_params_32), SNDRV_LSM_SET_MODULE_PARAMS_32 = _IOW('U', 0x0B, struct snd_lsm_module_params_32), + SNDRV_LSM_EVENT_STATUS_V3_32 = + _IOW('U', 0x0F, struct snd_lsm_event_status_v3_32), }; static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, @@ -1178,6 +1346,73 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, break; } + case SNDRV_LSM_EVENT_STATUS_V3_32: { + struct snd_lsm_event_status_v3_32 userarg32, *user32 = NULL; + struct snd_lsm_event_status_v3 *user = NULL; + + if (copy_from_user(&userarg32, arg, sizeof(userarg32))) { + dev_err(rtd->dev, "%s: err copyuser ioctl %s\n", + __func__, "SNDRV_LSM_EVENT_STATUS_V3_32"); + return -EFAULT; + } + + if (userarg32.payload_size > + LISTEN_MAX_STATUS_PAYLOAD_SIZE) { + pr_err("%s: payload_size %d is invalid, max allowed = %d\n", + __func__, userarg32.payload_size, + LISTEN_MAX_STATUS_PAYLOAD_SIZE); + return -EINVAL; + } + + size = sizeof(*user) + userarg32.payload_size; + user = kmalloc(size, GFP_KERNEL); + if (!user) { + dev_err(rtd->dev, + "%s: Allocation failed event status size %d\n", + __func__, size); + return -EFAULT; + } + cmd = SNDRV_LSM_EVENT_STATUS_V3; + user->payload_size = userarg32.payload_size; + err = msm_lsm_ioctl_shared(substream, cmd, user); + + /* Update size with actual payload size */ + size = sizeof(userarg32) + user->payload_size; + if (!err && !access_ok(VERIFY_WRITE, arg, size)) { + dev_err(rtd->dev, + "%s: write verify failed size %d\n", + __func__, size); + err = -EFAULT; + } + if (!err) { + user32 = kmalloc(size, GFP_KERNEL); + if (!user32) { + dev_err(rtd->dev, + "%s: Allocation event user status size %d\n", + __func__, size); + err = -EFAULT; + } else { + user32->timestamp_lsw = user->timestamp_lsw; + user32->timestamp_msw = user->timestamp_msw; + user32->status = user->status; + user32->payload_size = user->payload_size; + memcpy(user32->payload, + user->payload, user32->payload_size); + } + } + if (!err && (copy_to_user(arg, user32, size))) { + dev_err(rtd->dev, "%s: failed to copy payload %d", + __func__, size); + err = -EFAULT; + } + kfree(user); + kfree(user32); + if (err) + dev_err(rtd->dev, "%s: lsmevent failed %d", + __func__, err); + break; + } + case SNDRV_LSM_REG_SND_MODEL_V2_32: { struct snd_lsm_sound_model_v2_32 snd_modelv232; struct snd_lsm_sound_model_v2 snd_modelv2; @@ -1573,6 +1808,67 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, "%s: lsmevent failed %d", __func__, err); return err; } + + case SNDRV_LSM_EVENT_STATUS_V3: { + struct snd_lsm_event_status_v3 *user = NULL; + struct snd_lsm_event_status_v3 userarg; + + dev_dbg(rtd->dev, + "%s: SNDRV_LSM_EVENT_STATUS_V3\n", __func__); + if (!arg) { + dev_err(rtd->dev, + "%s: Invalid params event_status_v3\n", + __func__); + return -EINVAL; + } + if (copy_from_user(&userarg, arg, sizeof(userarg))) { + dev_err(rtd->dev, + "%s: err copyuser event_status_v3\n", + __func__); + return -EFAULT; + } + + if (userarg.payload_size > + LISTEN_MAX_STATUS_PAYLOAD_SIZE) { + pr_err("%s: payload_size %d is invalid, max allowed = %d\n", + __func__, userarg.payload_size, + LISTEN_MAX_STATUS_PAYLOAD_SIZE); + return -EINVAL; + } + + size = sizeof(struct snd_lsm_event_status_v3) + + userarg.payload_size; + user = kmalloc(size, GFP_KERNEL); + if (!user) { + dev_err(rtd->dev, + "%s: Allocation failed event status size %d\n", + __func__, size); + return -EFAULT; + } + user->payload_size = userarg.payload_size; + err = msm_lsm_ioctl_shared(substream, cmd, user); + + /* Update size with actual payload size */ + size = sizeof(*user) + user->payload_size; + if (!err && !access_ok(VERIFY_WRITE, arg, size)) { + dev_err(rtd->dev, + "%s: write verify failed size %d\n", + __func__, size); + err = -EFAULT; + } + if (!err && (copy_to_user(arg, user, size))) { + dev_err(rtd->dev, + "%s: failed to copy payload %d", + __func__, size); + err = -EFAULT; + } + kfree(user); + if (err) + dev_err(rtd->dev, + "%s: lsm_event_v3 failed %d", __func__, err); + break; + } + default: err = msm_lsm_ioctl_shared(substream, cmd, arg); break; @@ -1640,6 +1936,11 @@ static int msm_lsm_open(struct snd_pcm_substream *substream) return -ENOMEM; } prtd->lsm_client->opened = false; + prtd->lsm_client->session_state = IDLE; + prtd->lsm_client->poll_enable = true; + prtd->lsm_client->perf_mode = 0; + prtd->lsm_client->event_mode = LSM_EVENT_NON_TIME_STAMP_MODE; + return 0; } @@ -1648,6 +1949,7 @@ static int msm_lsm_prepare(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct lsm_priv *prtd = runtime->private_data; struct snd_soc_pcm_runtime *rtd; + int ret = 0; if (!substream->private_data) { pr_err("%s: Invalid private_data", __func__); @@ -1661,9 +1963,30 @@ static int msm_lsm_prepare(struct snd_pcm_substream *substream) "%s: LSM client data ptr is NULL\n", __func__); return -EINVAL; } + + if (q6lsm_set_media_fmt_params(prtd->lsm_client)) + dev_dbg(rtd->dev, + "%s: failed to set lsm media fmt params\n", __func__); + + if (prtd->lsm_client->session_state == IDLE) { + ret = msm_pcm_routing_reg_phy_compr_stream( + rtd->dai_link->be_id, + prtd->lsm_client->perf_mode, + prtd->lsm_client->session, + SNDRV_PCM_STREAM_CAPTURE, + LISTEN); + if (ret) { + dev_err(rtd->dev, + "%s: register phy compr stream failed %d\n", + __func__, ret); + return ret; + } + } + + prtd->lsm_client->session_state = RUNNING; prtd->lsm_client->started = false; runtime->private_data = prtd; - return 0; + return ret; } static int msm_lsm_close(struct snd_pcm_substream *substream) @@ -1712,6 +2035,9 @@ static int msm_lsm_close(struct snd_pcm_substream *substream) __func__); } + msm_pcm_routing_dereg_phy_stream(rtd->dai_link->be_id, + SNDRV_PCM_STREAM_CAPTURE); + if (prtd->lsm_client->opened) { q6lsm_close(prtd->lsm_client); prtd->lsm_client->opened = false; @@ -1733,7 +2059,7 @@ static int msm_lsm_hw_params(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime = substream->runtime; struct lsm_priv *prtd = runtime->private_data; - struct lsm_lab_hw_params *hw_params = NULL; + struct lsm_hw_params *hw_params = NULL; struct snd_soc_pcm_runtime *rtd; if (!substream->private_data) { @@ -1749,25 +2075,36 @@ static int msm_lsm_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } hw_params = &prtd->lsm_client->hw_params; - hw_params->sample_rate = params_rate(params); - hw_params->sample_size = - (params_format(params) == SNDRV_PCM_FORMAT_S16_LE) ? 16 : 0; + hw_params->num_chs = params_channels(params); hw_params->period_count = params_periods(params); - if (hw_params->sample_rate != 16000 || hw_params->sample_size != 16 || - hw_params->period_count == 0) { + hw_params->sample_rate = params_rate(params); + if (((hw_params->sample_rate != 16000) && + (hw_params->sample_rate != 48000)) || + (hw_params->period_count == 0)) { dev_err(rtd->dev, - "%s: Invalid params sample rate %d sample size %d period count %d", + "%s: Invalid Params sample rate %d period count %d\n", __func__, hw_params->sample_rate, - hw_params->sample_size, - hw_params->period_count); + hw_params->period_count); return -EINVAL; } + + if (params_format(params) == SNDRV_PCM_FORMAT_S16_LE) { + hw_params->sample_size = 16; + } else if (params_format(params) == SNDRV_PCM_FORMAT_S24_LE) { + hw_params->sample_size = 24; + } else { + dev_err(rtd->dev, "%s: Invalid Format 0x%x\n", + __func__, params_format(params)); + return -EINVAL; + } + hw_params->buf_sz = params_buffer_bytes(params) / - hw_params->period_count; + hw_params->period_count; dev_dbg(rtd->dev, - "%s: sample rate %d sample size %d buffer size %d period count %d\n", - __func__, hw_params->sample_rate, hw_params->sample_size, - hw_params->buf_sz, hw_params->period_count); + "%s: channels %d sample rate %d sample size %d buffer size %d period count %d\n", + __func__, hw_params->num_chs, hw_params->sample_rate, + hw_params->sample_size, hw_params->buf_sz, + hw_params->period_count); return 0; } @@ -1863,6 +2200,109 @@ static int msm_lsm_pcm_copy(struct snd_pcm_substream *substream, int ch, return 0; } +static int msm_lsm_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u64 fe_id = kcontrol->private_value; + int app_type; + int acdb_dev_id; + int sample_rate; + + pr_debug("%s: fe_id- %llu\n", __func__, fe_id); + if ((fe_id < MSM_FRONTEND_DAI_LSM1) || + (fe_id > MSM_FRONTEND_DAI_LSM8)) { + pr_err("%s: Received out of bounds fe_id %llu\n", + __func__, fe_id); + return -EINVAL; + } + + app_type = ucontrol->value.integer.value[0]; + acdb_dev_id = ucontrol->value.integer.value[1]; + sample_rate = ucontrol->value.integer.value[2]; + + pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d session_type- %d\n", + __func__, app_type, acdb_dev_id, sample_rate, SESSION_TYPE_TX); + msm_pcm_routing_reg_stream_app_type_cfg(fe_id, app_type, + acdb_dev_id, sample_rate, SESSION_TYPE_TX); + + return 0; +} + +static int msm_lsm_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u64 fe_id = kcontrol->private_value; + int ret = 0; + int app_type; + int acdb_dev_id; + int sample_rate; + + pr_debug("%s: fe_id- %llu\n", __func__, fe_id); + if ((fe_id < MSM_FRONTEND_DAI_LSM1) || + (fe_id > MSM_FRONTEND_DAI_LSM8)) { + pr_err("%s: Received out of bounds fe_id %llu\n", + __func__, fe_id); + return -EINVAL; + } + + ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, SESSION_TYPE_TX, + &app_type, &acdb_dev_id, &sample_rate); + if (ret < 0) { + pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n", + __func__, ret); + goto done; + } + + ucontrol->value.integer.value[0] = app_type; + ucontrol->value.integer.value[1] = acdb_dev_id; + ucontrol->value.integer.value[2] = sample_rate; + pr_debug("%s: fedai_id %llu, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n", + __func__, fe_id, SESSION_TYPE_TX, + app_type, acdb_dev_id, sample_rate); +done: + return ret; +} + +static int msm_lsm_add_app_type_controls(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_pcm *pcm = rtd->pcm; + struct snd_pcm_usr *app_type_info; + struct snd_kcontrol *kctl; + const char *mixer_ctl_name = "Listen Stream"; + const char *deviceNo = "NN"; + const char *suffix = "App Type Cfg"; + int ctl_len, ret = 0; + + ctl_len = strlen(mixer_ctl_name) + 1 + + strlen(deviceNo) + 1 + strlen(suffix) + 1; + pr_debug("%s: Listen app type cntrl add\n", __func__); + ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_CAPTURE, + NULL, 1, ctl_len, rtd->dai_link->be_id, + &app_type_info); + if (ret < 0) { + pr_err("%s: Listen app type cntrl add failed: %d\n", + __func__, ret); + return ret; + } + kctl = app_type_info->kctl; + snprintf(kctl->id.name, ctl_len, "%s %d %s", + mixer_ctl_name, rtd->pcm->device, suffix); + kctl->put = msm_lsm_app_type_cfg_ctl_put; + kctl->get = msm_lsm_app_type_cfg_ctl_get; + return 0; +} + +static int msm_lsm_add_controls(struct snd_soc_pcm_runtime *rtd) +{ + int ret = 0; + + ret = msm_lsm_add_app_type_controls(rtd); + if (ret) + pr_err("%s, add app type controls failed:%d\n", __func__, ret); + + return ret; +} + static struct snd_pcm_ops msm_lsm_ops = { .open = msm_lsm_open, .close = msm_lsm_close, @@ -1877,11 +2317,16 @@ static struct snd_pcm_ops msm_lsm_ops = { static int msm_asoc_lsm_new(struct snd_soc_pcm_runtime *rtd) { struct snd_card *card = rtd->card->snd_card; + int ret = 0; if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - return 0; + ret = msm_lsm_add_controls(rtd); + if (ret) + pr_err("%s, kctl add failed:%d\n", __func__, ret); + + return ret; } static int msm_asoc_lsm_probe(struct snd_soc_platform *platform) diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index 2d410170f48d..30522ac023cd 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -72,9 +72,12 @@ static int tert_mi2s_switch_enable; static int quat_mi2s_switch_enable; static int fm_pcmrx_switch_enable; static int usb_switch_enable; -static int lsm_mux_slim_port; +static int lsm_port_index; static int slim0_rx_aanc_fb_port; static int msm_route_ec_ref_rx; +static int msm_ec_ref_ch = 4; +static int msm_ec_ref_bit_format = SNDRV_PCM_FORMAT_S16_LE; +static int msm_ec_ref_sampling_rate = 48000; static uint32_t voc_session_id = ALL_SESSION_VSID; static int msm_route_ext_ec_ref; static bool is_custom_stereo_on; @@ -88,6 +91,8 @@ enum { MADSWAUDIO, }; +#define ADM_LSM_PORT_INDEX 9 + #define SLIMBUS_0_TX_TEXT "SLIMBUS_0_TX" #define SLIMBUS_1_TX_TEXT "SLIMBUS_1_TX" #define SLIMBUS_2_TX_TEXT "SLIMBUS_2_TX" @@ -96,12 +101,14 @@ enum { #define SLIMBUS_TX_VI_TEXT "SLIMBUS_TX_VI" #define SLIMBUS_5_TX_TEXT "SLIMBUS_5_TX" #define TERT_MI2S_TX_TEXT "TERT_MI2S_TX" +#define QUAT_MI2S_TX_TEXT "QUAT_MI2S_TX" +#define ADM_LSM_TX_TEXT "ADM_LSM_TX" #define LSM_FUNCTION_TEXT "LSM Function" -static const char * const mad_audio_mux_text[] = { +static const char * const lsm_port_text[] = { "None", SLIMBUS_0_TX_TEXT, SLIMBUS_1_TX_TEXT, SLIMBUS_2_TX_TEXT, - SLIMBUS_3_TX_TEXT, SLIMBUS_4_TX_TEXT, SLIMBUS_TX_VI_TEXT, - SLIMBUS_5_TX_TEXT, TERT_MI2S_TX_TEXT + SLIMBUS_3_TX_TEXT, SLIMBUS_4_TX_TEXT, SLIMBUS_5_TX_TEXT, + TERT_MI2S_TX_TEXT, QUAT_MI2S_TX_TEXT, ADM_LSM_TX_TEXT }; struct msm_pcm_route_bdai_pp_params { @@ -270,254 +277,262 @@ static void msm_pcm_routng_cfg_matrix_map_pp(struct route_payload payload, #define SLIMBUS_EXTPROC_RX AFE_PORT_INVALID struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = { - { PRIMARY_I2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_I2S_RX}, - { PRIMARY_I2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_I2S_TX}, - { SLIMBUS_0_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_0_RX}, - { SLIMBUS_0_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_0_TX}, - { HDMI_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_HDMI}, - { INT_BT_SCO_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_SCO_RX}, - { INT_BT_SCO_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_SCO_TX}, - { INT_FM_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_FM_RX}, - { INT_FM_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_FM_TX}, - { RT_PROXY_PORT_001_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_AFE_PCM_RX}, - { RT_PROXY_PORT_001_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_AFE_PCM_TX}, - { AFE_PORT_ID_PRIMARY_PCM_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { PRIMARY_I2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_I2S_RX}, + { PRIMARY_I2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_I2S_TX}, + { SLIMBUS_0_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_0_RX}, + { SLIMBUS_0_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_0_TX}, + { HDMI_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_HDMI}, + { INT_BT_SCO_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_SCO_RX}, + { INT_BT_SCO_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_SCO_TX}, + { INT_FM_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_FM_RX}, + { INT_FM_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_FM_TX}, + { RT_PROXY_PORT_001_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, + LPASS_BE_AFE_PCM_RX}, + { RT_PROXY_PORT_001_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, + LPASS_BE_AFE_PCM_TX}, + { AFE_PORT_ID_PRIMARY_PCM_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_AUXPCM_RX}, - { AFE_PORT_ID_PRIMARY_PCM_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_PCM_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_AUXPCM_TX}, - { VOICE_PLAYBACK_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { VOICE_PLAYBACK_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_VOICE_PLAYBACK_TX}, - { VOICE2_PLAYBACK_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { VOICE2_PLAYBACK_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_VOICE2_PLAYBACK_TX}, - { VOICE_RECORD_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_INCALL_RECORD_RX}, - { VOICE_RECORD_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_INCALL_RECORD_TX}, - { MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_MI2S_RX}, - { MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_MI2S_TX}, - { SECONDARY_I2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_I2S_RX}, - { SLIMBUS_1_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_1_RX}, - { SLIMBUS_1_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_1_TX}, - { SLIMBUS_2_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_2_RX}, - { SLIMBUS_2_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_2_TX}, - { SLIMBUS_3_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_3_RX}, - { SLIMBUS_3_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_3_TX}, - { SLIMBUS_4_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_4_RX}, - { SLIMBUS_4_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_4_TX}, - { SLIMBUS_5_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_5_RX}, - { SLIMBUS_5_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_5_TX}, - { SLIMBUS_6_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_6_RX}, - { SLIMBUS_6_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_6_TX}, - { SLIMBUS_7_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_7_RX}, - { SLIMBUS_7_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_7_TX}, - { SLIMBUS_8_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_8_RX}, - { SLIMBUS_8_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_8_TX}, - { SLIMBUS_EXTPROC_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_STUB_RX}, - { SLIMBUS_EXTPROC_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_STUB_TX}, - { SLIMBUS_EXTPROC_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_STUB_1_TX}, - { AFE_PORT_ID_QUATERNARY_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { VOICE_RECORD_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, + LPASS_BE_INCALL_RECORD_RX}, + { VOICE_RECORD_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, + LPASS_BE_INCALL_RECORD_TX}, + { MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_MI2S_RX}, + { MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_MI2S_TX}, + { SECONDARY_I2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_I2S_RX}, + { SLIMBUS_1_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_1_RX}, + { SLIMBUS_1_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_1_TX}, + { SLIMBUS_2_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_2_RX}, + { SLIMBUS_2_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_2_TX}, + { SLIMBUS_3_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_3_RX}, + { SLIMBUS_3_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_3_TX}, + { SLIMBUS_4_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_4_RX}, + { SLIMBUS_4_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_4_TX}, + { SLIMBUS_5_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_5_RX}, + { SLIMBUS_5_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_5_TX}, + { SLIMBUS_6_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_6_RX}, + { SLIMBUS_6_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_6_TX}, + { SLIMBUS_7_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_7_RX}, + { SLIMBUS_7_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_7_TX}, + { SLIMBUS_8_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_8_RX}, + { SLIMBUS_8_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_8_TX}, + { SLIMBUS_EXTPROC_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_STUB_RX}, + { SLIMBUS_EXTPROC_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_STUB_TX}, + { SLIMBUS_EXTPROC_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_STUB_1_TX}, + { AFE_PORT_ID_QUATERNARY_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_MI2S_RX}, - { AFE_PORT_ID_QUATERNARY_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_MI2S_TX}, - { AFE_PORT_ID_SECONDARY_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_MI2S_RX}, - { AFE_PORT_ID_SECONDARY_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_MI2S_TX}, - { AFE_PORT_ID_PRIMARY_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_MI2S_RX}, - { AFE_PORT_ID_PRIMARY_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_MI2S_TX}, - { AFE_PORT_ID_TERTIARY_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_MI2S_RX}, - { AFE_PORT_ID_TERTIARY_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_MI2S_TX}, - { AUDIO_PORT_ID_I2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AUDIO_PORT_ID_I2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_AUDIO_I2S_RX}, - { AFE_PORT_ID_SECONDARY_PCM_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_PCM_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_AUXPCM_RX}, - { AFE_PORT_ID_SECONDARY_PCM_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_PCM_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_AUXPCM_TX}, - { AFE_PORT_ID_SPDIF_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SPDIF_RX}, - { AFE_PORT_ID_SECONDARY_MI2S_RX_SD1, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SPDIF_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SPDIF_RX}, + { AFE_PORT_ID_SECONDARY_MI2S_RX_SD1, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_MI2S_RX_SD1}, - { AFE_PORT_ID_QUINARY_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUINARY_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUIN_MI2S_RX}, - { AFE_PORT_ID_QUINARY_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUINARY_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUIN_MI2S_TX}, - { AFE_PORT_ID_SENARY_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SENARY_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SENARY_MI2S_TX}, - { AFE_PORT_ID_PRIMARY_TDM_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_RX_0}, - { AFE_PORT_ID_PRIMARY_TDM_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_TX_0}, - { AFE_PORT_ID_PRIMARY_TDM_RX_1, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_RX_1, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_RX_1}, - { AFE_PORT_ID_PRIMARY_TDM_TX_1, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_TX_1, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_TX_1}, - { AFE_PORT_ID_PRIMARY_TDM_RX_2, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_RX_2, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_RX_2}, - { AFE_PORT_ID_PRIMARY_TDM_TX_2, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_TX_2, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_TX_2}, - { AFE_PORT_ID_PRIMARY_TDM_RX_3, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_RX_3, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_RX_3}, - { AFE_PORT_ID_PRIMARY_TDM_TX_3, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_TX_3, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_TX_3}, - { AFE_PORT_ID_PRIMARY_TDM_RX_4, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_RX_4, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_RX_4}, - { AFE_PORT_ID_PRIMARY_TDM_TX_4, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_TX_4, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_TX_4}, - { AFE_PORT_ID_PRIMARY_TDM_RX_5, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_RX_5, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_RX_5}, - { AFE_PORT_ID_PRIMARY_TDM_TX_5, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_TX_5, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_TX_5}, - { AFE_PORT_ID_PRIMARY_TDM_RX_6, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_RX_6, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_RX_6}, - { AFE_PORT_ID_PRIMARY_TDM_TX_6, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_TX_6, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_TX_6}, - { AFE_PORT_ID_PRIMARY_TDM_RX_7, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_RX_7, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_RX_7}, - { AFE_PORT_ID_PRIMARY_TDM_TX_7, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_TX_7, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_TX_7}, - { AFE_PORT_ID_SECONDARY_TDM_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_RX_0}, - { AFE_PORT_ID_SECONDARY_TDM_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_TX_0}, - { AFE_PORT_ID_SECONDARY_TDM_RX_1, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_RX_1, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_RX_1}, - { AFE_PORT_ID_SECONDARY_TDM_TX_1, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_TX_1, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_TX_1}, - { AFE_PORT_ID_SECONDARY_TDM_RX_2, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_RX_2, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_RX_2}, - { AFE_PORT_ID_SECONDARY_TDM_TX_2, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_TX_2, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_TX_2}, - { AFE_PORT_ID_SECONDARY_TDM_RX_3, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_RX_3, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_RX_3}, - { AFE_PORT_ID_SECONDARY_TDM_TX_3, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_TX_3, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_TX_3}, - { AFE_PORT_ID_SECONDARY_TDM_RX_4, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_RX_4, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_RX_4}, - { AFE_PORT_ID_SECONDARY_TDM_TX_4, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_TX_4, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_TX_4}, - { AFE_PORT_ID_SECONDARY_TDM_RX_5, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_RX_5, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_RX_5}, - { AFE_PORT_ID_SECONDARY_TDM_TX_5, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_TX_5, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_TX_5}, - { AFE_PORT_ID_SECONDARY_TDM_RX_6, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_RX_6, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_RX_6}, - { AFE_PORT_ID_SECONDARY_TDM_TX_6, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_TX_6, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_TX_6}, - { AFE_PORT_ID_SECONDARY_TDM_RX_7, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_RX_7, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_RX_7}, - { AFE_PORT_ID_SECONDARY_TDM_TX_7, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_TX_7, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_TX_7}, - { AFE_PORT_ID_TERTIARY_TDM_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_RX_0}, - { AFE_PORT_ID_TERTIARY_TDM_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_TX_0}, - { AFE_PORT_ID_TERTIARY_TDM_RX_1, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_RX_1, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_RX_1}, - { AFE_PORT_ID_TERTIARY_TDM_TX_1, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_TX_1, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_TX_1}, - { AFE_PORT_ID_TERTIARY_TDM_RX_2, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_RX_2, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_RX_2}, - { AFE_PORT_ID_TERTIARY_TDM_TX_2, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_TX_2, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_TX_2}, - { AFE_PORT_ID_TERTIARY_TDM_RX_3, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_RX_3, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_RX_3}, - { AFE_PORT_ID_TERTIARY_TDM_TX_3, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_TX_3, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_TX_3}, - { AFE_PORT_ID_TERTIARY_TDM_RX_4, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_RX_4, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_RX_4}, - { AFE_PORT_ID_TERTIARY_TDM_TX_4, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_TX_4, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_TX_4}, - { AFE_PORT_ID_TERTIARY_TDM_RX_5, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_RX_5, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_RX_5}, - { AFE_PORT_ID_TERTIARY_TDM_TX_5, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_TX_5, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_TX_5}, - { AFE_PORT_ID_TERTIARY_TDM_RX_6, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_RX_6, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_RX_6}, - { AFE_PORT_ID_TERTIARY_TDM_TX_6, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_TX_6, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_TX_6}, - { AFE_PORT_ID_TERTIARY_TDM_RX_7, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_RX_7, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_RX_7}, - { AFE_PORT_ID_TERTIARY_TDM_TX_7, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_TX_7, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_TX_7}, - { AFE_PORT_ID_QUATERNARY_TDM_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_RX_0}, - { AFE_PORT_ID_QUATERNARY_TDM_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_TX_0}, - { AFE_PORT_ID_QUATERNARY_TDM_RX_1, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_RX_1, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_RX_1}, - { AFE_PORT_ID_QUATERNARY_TDM_TX_1, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_TX_1, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_TX_1}, - { AFE_PORT_ID_QUATERNARY_TDM_RX_2, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_RX_2, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_RX_2}, - { AFE_PORT_ID_QUATERNARY_TDM_TX_2, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_TX_2, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_TX_2}, - { AFE_PORT_ID_QUATERNARY_TDM_RX_3, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_RX_3, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_RX_3}, - { AFE_PORT_ID_QUATERNARY_TDM_TX_3, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_TX_3, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_TX_3}, - { AFE_PORT_ID_QUATERNARY_TDM_RX_4, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_RX_4, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_RX_4}, - { AFE_PORT_ID_QUATERNARY_TDM_TX_4, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_TX_4, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_TX_4}, - { AFE_PORT_ID_QUATERNARY_TDM_RX_5, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_RX_5, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_RX_5}, - { AFE_PORT_ID_QUATERNARY_TDM_TX_5, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_TX_5, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_TX_5}, - { AFE_PORT_ID_QUATERNARY_TDM_RX_6, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_RX_6, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_RX_6}, - { AFE_PORT_ID_QUATERNARY_TDM_TX_6, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_TX_6, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_TX_6}, - { AFE_PORT_ID_QUATERNARY_TDM_RX_7, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_RX_7, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_RX_7}, - { AFE_PORT_ID_QUATERNARY_TDM_TX_7, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_TX_7, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_TX_7}, - { INT_BT_A2DP_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_A2DP_RX}, - { 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}, - { AFE_PORT_ID_TERTIARY_PCM_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { INT_BT_A2DP_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_A2DP_RX}, + { 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}, + { AFE_PORT_ID_TERTIARY_PCM_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_AUXPCM_RX}, - { AFE_PORT_ID_TERTIARY_PCM_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_PCM_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_AUXPCM_TX}, - { AFE_PORT_ID_QUATERNARY_PCM_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_PCM_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_AUXPCM_RX}, - { AFE_PORT_ID_QUATERNARY_PCM_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_PCM_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_AUXPCM_TX}, - { AFE_PORT_ID_INT0_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT0_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT0_MI2S_RX}, - { AFE_PORT_ID_INT0_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT0_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT0_MI2S_TX}, - { AFE_PORT_ID_INT1_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT1_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT1_MI2S_RX}, - { AFE_PORT_ID_INT1_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT1_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT1_MI2S_TX}, - { AFE_PORT_ID_INT2_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT2_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT2_MI2S_RX}, - { AFE_PORT_ID_INT2_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT2_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT2_MI2S_TX}, - { AFE_PORT_ID_INT3_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT3_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT3_MI2S_RX}, - { AFE_PORT_ID_INT3_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT3_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT3_MI2S_TX}, - { AFE_PORT_ID_INT4_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT4_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT4_MI2S_RX}, - { AFE_PORT_ID_INT4_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT4_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT4_MI2S_TX}, - { AFE_PORT_ID_INT5_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT5_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT5_MI2S_RX}, - { AFE_PORT_ID_INT5_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT5_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT5_MI2S_TX}, - { AFE_PORT_ID_INT6_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT6_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT6_MI2S_RX}, - { AFE_PORT_ID_INT6_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT6_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT6_MI2S_TX}, - { SLIMBUS_TX_VI, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_TX_VI}, + { SLIMBUS_TX_VI, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_TX_VI}, }; -/* Track ASM playback & capture sessions of DAI */ +/* Track ASM playback & capture sessions of DAI + * Track LSM listen sessions + */ static struct msm_pcm_routing_fdai_data - fe_dai_map[MSM_FRONTEND_DAI_MM_SIZE][2] = { + fe_dai_map[MSM_FRONTEND_DAI_MAX][2] = { /* MULTIMEDIA1 */ {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, @@ -575,13 +590,80 @@ static struct msm_pcm_routing_fdai_data /* MULTIMEDIA19 */ {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* CS_VOICE */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* VOIP */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* AFE_RX */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* AFE_TX */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* VOICE_STUB */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* VOLTE */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* DTMF_RX */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* VOICE2 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* QCHAT */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* VOLTE_STUB */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* LSM1 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* LSM2 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* LSM3 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* LSM4 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* LSM5 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* LSM6 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* LSM7 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* LSM8 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* VOICE2_STUB */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* VOWLAN */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* VOICEMMODE1 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* VOICEMMODE2 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, }; -static unsigned long session_copp_map[MSM_FRONTEND_DAI_MM_SIZE][2] +static unsigned long session_copp_map[MSM_FRONTEND_DAI_MAX][2] [MSM_BACKEND_DAI_MAX]; static struct msm_pcm_routing_app_type_data app_type_cfg[MAX_APP_TYPES]; +static struct msm_pcm_routing_app_type_data lsm_app_type_cfg[MAX_APP_TYPES]; static struct msm_pcm_stream_app_type_cfg - fe_dai_app_type_cfg[MSM_FRONTEND_DAI_MM_SIZE][2]; + fe_dai_app_type_cfg[MSM_FRONTEND_DAI_MAX][2]; /* The caller of this should aqcuire routing lock */ void msm_pcm_routing_get_bedai_info(int be_idx, @@ -624,13 +706,39 @@ static int msm_pcm_routing_get_app_type_idx(int app_type) return 0; } +static int msm_pcm_routing_get_lsm_app_type_idx(int app_type) +{ + int idx; + + pr_debug("%s: app_type: %d\n", __func__, app_type); + for (idx = 0; idx < MAX_APP_TYPES; idx++) { + if (lsm_app_type_cfg[idx].app_type == app_type) + return idx; + } + pr_debug("%s: App type not available, fallback to default\n", __func__); + return 0; +} + +static bool is_mm_lsm_fe_id(int fe_id) +{ + bool rc = true; + + if (fe_id > MSM_FRONTEND_DAI_MM_MAX_ID && + ((fe_id < MSM_FRONTEND_DAI_LSM1) || + (fe_id > MSM_FRONTEND_DAI_LSM8))) { + rc = false; + } + return rc; +} + + void msm_pcm_routing_reg_stream_app_type_cfg(int fedai_id, int app_type, int acdb_dev_id, int sample_rate, int session_type) { pr_debug("%s: fedai_id %d, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n", __func__, fedai_id, session_type, app_type, acdb_dev_id, sample_rate); - if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) { + if (!is_mm_lsm_fe_id(fedai_id)) { pr_err("%s: Invalid machine driver ID %d\n", __func__, fedai_id); return; @@ -677,7 +785,7 @@ int msm_pcm_routing_get_stream_app_type_cfg(int fedai_id, int session_type, pr_err("%s: NULL pointer sent for sample rate\n", __func__); ret = -EINVAL; goto done; - } else if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) { + } else if (!is_mm_lsm_fe_id(fedai_id)) { pr_err("%s: Invalid FE ID %d\n", __func__, fedai_id); ret = -EINVAL; @@ -791,7 +899,8 @@ static uint8_t is_be_dai_extproc(int be_dai) } static void msm_pcm_routing_build_matrix(int fedai_id, int sess_type, - int path_type, int perf_mode) + int path_type, int perf_mode, + uint32_t passthr_mode) { int i, port_type, j, num_copps = 0; struct route_payload payload; @@ -804,7 +913,7 @@ static void msm_pcm_routing_build_matrix(int fedai_id, int sess_type, if (!is_be_dai_extproc(i) && (afe_get_port_type(msm_bedais[i].port_id) == port_type) && (msm_bedais[i].active) && - (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) { + (test_bit(fedai_id, &msm_bedais[i].fe_sessions[0]))) { for (j = 0; j < MAX_COPPS_PER_PORT; j++) { unsigned long copp = session_copp_map[fedai_id][sess_type][i]; @@ -827,7 +936,7 @@ static void msm_pcm_routing_build_matrix(int fedai_id, int sess_type, fe_dai_app_type_cfg[fedai_id][sess_type].acdb_dev_id; payload.sample_rate = fe_dai_app_type_cfg[fedai_id][sess_type].sample_rate; - adm_matrix_map(path_type, payload, perf_mode); + adm_matrix_map(path_type, payload, perf_mode, passthr_mode); msm_pcm_routng_cfg_matrix_map_pp(payload, path_type, perf_mode); } } @@ -861,7 +970,7 @@ void msm_pcm_routing_reg_psthr_stream(int fedai_id, int dspst_id, if (!is_be_dai_extproc(i) && (afe_get_port_type(msm_bedais[i].port_id) == port_type) && (msm_bedais[i].active) && - (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) { + (test_bit(fedai_id, &msm_bedais[i].fe_sessions[0]))) { mode = afe_get_port_type(msm_bedais[i].port_id); adm_connect_afe_port(mode, dspst_id, msm_bedais[i].port_id); @@ -871,28 +980,51 @@ void msm_pcm_routing_reg_psthr_stream(int fedai_id, int dspst_id, mutex_unlock(&routing_lock); } +static bool route_check_fe_id_adm_support(int fe_id) +{ + bool rc = true; + + if ((fe_id >= MSM_FRONTEND_DAI_LSM1) && + (fe_id <= MSM_FRONTEND_DAI_LSM8)) { + /* fe id is listen while port is set to afe */ + if (lsm_port_index != ADM_LSM_PORT_INDEX) { + pr_debug("%s: fe_id %d, lsm mux slim port %d\n", + __func__, fe_id, lsm_port_index); + rc = false; + } + } + + return rc; +} + int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, int dspst_id, int stream_type, - uint32_t compr_passthr_mode) + uint32_t passthr_mode) { int i, j, session_type, path_type, port_type, topology, num_copps = 0; struct route_payload payload; u32 channels, sample_rate; u16 bit_width = 16; + bool is_lsm; pr_debug("%s:fe_id[%d] perf_mode[%d] id[%d] stream_type[%d] passt[%d]", __func__, fe_id, perf_mode, dspst_id, - stream_type, compr_passthr_mode); - - if (fe_id > MSM_FRONTEND_DAI_MM_MAX_ID) { + stream_type, passthr_mode); + if (!is_mm_lsm_fe_id(fe_id)) { /* bad ID assigned in machine driver */ pr_err("%s: bad MM ID %d\n", __func__, fe_id); return -EINVAL; } + if (!route_check_fe_id_adm_support(fe_id)) { + /* ignore adm open if not supported for fe_id */ + pr_debug("%s: No ADM support for fe id %d\n", __func__, fe_id); + return 0; + } + if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) { session_type = SESSION_TYPE_RX; - if (compr_passthr_mode != LEGACY_PCM) + if (passthr_mode != LEGACY_PCM) path_type = ADM_PATH_COMPRESSED_RX; else path_type = ADM_PATH_PLAYBACK; @@ -906,6 +1038,8 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, return -EINVAL; } + is_lsm = (fe_id >= MSM_FRONTEND_DAI_LSM1) && + (fe_id <= MSM_FRONTEND_DAI_LSM8); mutex_lock(&routing_lock); payload.num_copps = 0; /* only RX needs to use payload */ @@ -913,14 +1047,14 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, /* re-enable EQ if active */ msm_qti_pp_send_eq_values(fe_id); for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) { - if (test_bit(fe_id, &msm_bedais[i].fe_sessions)) - msm_bedais[i].compr_passthr_mode = compr_passthr_mode; + if (test_bit(fe_id, &msm_bedais[i].fe_sessions[0])) + msm_bedais[i].passthr_mode = passthr_mode; if (!is_be_dai_extproc(i) && (afe_get_port_type(msm_bedais[i].port_id) == port_type) && (msm_bedais[i].active) && - (test_bit(fe_id, &msm_bedais[i].fe_sessions))) { + (test_bit(fe_id, &msm_bedais[i].fe_sessions[0]))) { int app_type, app_type_idx, copp_idx, acdb_dev_id; /* @@ -936,7 +1070,15 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, msm_bedais[i].format); app_type = fe_dai_app_type_cfg[fe_id][session_type].app_type; - if (app_type) { + if (app_type && is_lsm) { + app_type_idx = + msm_pcm_routing_get_lsm_app_type_idx(app_type); + sample_rate = + fe_dai_app_type_cfg[fe_id][session_type]. + sample_rate; + bit_width = + lsm_app_type_cfg[app_type_idx].bit_width; + } else if (app_type) { app_type_idx = msm_pcm_routing_get_app_type_idx( app_type); @@ -951,9 +1093,10 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, fe_dai_app_type_cfg[fe_id][session_type].acdb_dev_id; topology = msm_routing_get_adm_topology(path_type, fe_id, session_type); - if (compr_passthr_mode == COMPRESSED_PASSTHROUGH_DSD) + + if (passthr_mode == COMPRESSED_PASSTHROUGH_DSD) topology = COMPRESS_PASSTHROUGH_NONE_TOPOLOGY; - pr_err("%s: Before adm open topology %d\n", __func__, + pr_debug("%s: Before adm open topology %d\n", __func__, topology); copp_idx = @@ -990,7 +1133,7 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, num_copps++; } } - if (compr_passthr_mode != COMPRESSED_PASSTHROUGH_DSD) { + if (passthr_mode != COMPRESSED_PASSTHROUGH_DSD) { msm_routing_send_device_pp_params( msm_bedais[i].port_id, copp_idx); @@ -1004,7 +1147,9 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, fe_dai_app_type_cfg[fe_id][session_type].app_type; payload.acdb_dev_id = fe_dai_app_type_cfg[fe_id][session_type].acdb_dev_id; - adm_matrix_map(path_type, payload, perf_mode); + payload.sample_rate = + fe_dai_app_type_cfg[fe_id][session_type].sample_rate; + adm_matrix_map(path_type, payload, perf_mode, passthr_mode); msm_pcm_routng_cfg_matrix_map_pp(payload, path_type, perf_mode); } mutex_unlock(&routing_lock); @@ -1055,6 +1200,7 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, struct route_payload payload; u32 channels, sample_rate; uint16_t bits_per_sample = 16; + uint32_t passthr_mode = LEGACY_PCM; if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) { /* bad ID assigned in machine driver */ @@ -1084,7 +1230,7 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, if (!is_be_dai_extproc(i) && (afe_get_port_type(msm_bedais[i].port_id) == port_type) && (msm_bedais[i].active) && - (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) { + (test_bit(fedai_id, &msm_bedais[i].fe_sessions[0]))) { int app_type, app_type_idx, copp_idx, acdb_dev_id; /* * check if ADM needs to be configured with different @@ -1094,7 +1240,7 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, channels = msm_bedais[i].channel; else channels = msm_bedais[i].adm_override_ch; - msm_bedais[i].compr_passthr_mode = + msm_bedais[i].passthr_mode = LEGACY_PCM; bits_per_sample = msm_routing_get_bit_width( @@ -1151,7 +1297,7 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, } } if ((perf_mode == LEGACY_PCM_MODE) && - (msm_bedais[i].compr_passthr_mode == + (msm_bedais[i].passthr_mode == LEGACY_PCM)) msm_pcm_routing_cfg_pp(msm_bedais[i].port_id, copp_idx, topology, @@ -1167,7 +1313,7 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, fe_dai_app_type_cfg[fedai_id][session_type].acdb_dev_id; payload.sample_rate = fe_dai_app_type_cfg[fedai_id][session_type].sample_rate; - adm_matrix_map(path_type, payload, perf_mode); + adm_matrix_map(path_type, payload, perf_mode, passthr_mode); msm_pcm_routng_cfg_matrix_map_pp(payload, path_type, perf_mode); } mutex_unlock(&routing_lock); @@ -1196,7 +1342,7 @@ void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type) int i, port_type, session_type, path_type, topology; struct msm_pcm_routing_fdai_data *fdai; - if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) { + if (!is_mm_lsm_fe_id(fedai_id)) { /* bad ID assigned in machine driver */ pr_err("%s: bad MM ID\n", __func__); return; @@ -1217,7 +1363,7 @@ void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type) if (!is_be_dai_extproc(i) && (afe_get_port_type(msm_bedais[i].port_id) == port_type) && (msm_bedais[i].active) && - (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) { + (test_bit(fedai_id, &msm_bedais[i].fe_sessions[0]))) { int idx; unsigned long copp = session_copp_map[fedai_id][session_type][i]; @@ -1242,7 +1388,7 @@ void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type) if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology || DS2_ADM_COPP_TOPOLOGY_ID == topology) && (fdai->perf_mode == LEGACY_PCM_MODE) && - (msm_bedais[i].compr_passthr_mode == + (msm_bedais[i].passthr_mode == LEGACY_PCM)) msm_pcm_routing_deinit_pp(msm_bedais[i].port_id, topology); @@ -1259,13 +1405,13 @@ static bool msm_pcm_routing_route_is_set(u16 be_id, u16 fe_id) { bool rc = false; - if (fe_id > MSM_FRONTEND_DAI_MM_MAX_ID) { + if (!is_mm_lsm_fe_id(fe_id)) { /* recheck FE ID in the mixer control defined in this file */ pr_err("%s: bad MM ID\n", __func__); return rc; } - if (test_bit(fe_id, &msm_bedais[be_id].fe_sessions)) + if (test_bit(fe_id, &msm_bedais[be_id].fe_sessions[0])) rc = true; return rc; @@ -1277,19 +1423,27 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set) u32 channels, sample_rate; uint16_t bits_per_sample = 16; struct msm_pcm_routing_fdai_data *fdai; + uint32_t passthr_mode = msm_bedais[reg].passthr_mode; + bool is_lsm; pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set); - if (val > MSM_FRONTEND_DAI_MM_MAX_ID) { + if (!is_mm_lsm_fe_id(val)) { /* recheck FE ID in the mixer control defined in this file */ pr_err("%s: bad MM ID\n", __func__); return; } + if (!route_check_fe_id_adm_support(val)) { + /* ignore adm open if not supported for fe_id */ + pr_debug("%s: No ADM support for fe id %d\n", __func__, val); + return; + } + if (afe_get_port_type(msm_bedais[reg].port_id) == MSM_AFE_PORT_TYPE_RX) { session_type = SESSION_TYPE_RX; - if (msm_bedais[reg].compr_passthr_mode != LEGACY_PCM) + if (passthr_mode != LEGACY_PCM) path_type = ADM_PATH_COMPRESSED_RX; else path_type = ADM_PATH_PLAYBACK; @@ -1297,15 +1451,17 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set) session_type = SESSION_TYPE_TX; path_type = ADM_PATH_LIVE_REC; } + is_lsm = (val >= MSM_FRONTEND_DAI_LSM1) && + (val <= MSM_FRONTEND_DAI_LSM8); mutex_lock(&routing_lock); if (set) { - if (!test_bit(val, &msm_bedais[reg].fe_sessions) && + if (!test_bit(val, &msm_bedais[reg].fe_sessions[0]) && ((msm_bedais[reg].port_id == VOICE_PLAYBACK_TX) || (msm_bedais[reg].port_id == VOICE2_PLAYBACK_TX))) voc_start_playback(set, msm_bedais[reg].port_id); - set_bit(val, &msm_bedais[reg].fe_sessions); + set_bit(val, &msm_bedais[reg].fe_sessions[0]); fdai = &fe_dai_map[val][session_type]; if (msm_bedais[reg].active && fdai->strm_id != INVALID_SESSION) { @@ -1336,7 +1492,15 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set) app_type = fe_dai_app_type_cfg[val][session_type].app_type; - if (app_type) { + if (app_type && is_lsm) { + app_type_idx = + msm_pcm_routing_get_lsm_app_type_idx(app_type); + sample_rate = + fe_dai_app_type_cfg[val][session_type]. + sample_rate; + bits_per_sample = + lsm_app_type_cfg[app_type_idx].bit_width; + } else if (app_type) { app_type_idx = msm_pcm_routing_get_app_type_idx(app_type); sample_rate = @@ -1381,20 +1545,20 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set) msm_pcm_routing_build_matrix(val, session_type, path_type, - fdai->perf_mode); + fdai->perf_mode, + passthr_mode); if ((fdai->perf_mode == LEGACY_PCM_MODE) && - (msm_bedais[reg].compr_passthr_mode == - LEGACY_PCM)) + (passthr_mode == LEGACY_PCM)) msm_pcm_routing_cfg_pp(msm_bedais[reg].port_id, copp_idx, topology, channels); } } else { - if (test_bit(val, &msm_bedais[reg].fe_sessions) && + if (test_bit(val, &msm_bedais[reg].fe_sessions[0]) && ((msm_bedais[reg].port_id == VOICE_PLAYBACK_TX) || (msm_bedais[reg].port_id == VOICE2_PLAYBACK_TX))) voc_start_playback(set, msm_bedais[reg].port_id); - clear_bit(val, &msm_bedais[reg].fe_sessions); + clear_bit(val, &msm_bedais[reg].fe_sessions[0]); fdai = &fe_dai_map[val][session_type]; if (msm_bedais[reg].active && fdai->strm_id != INVALID_SESSION) { @@ -1419,14 +1583,14 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set) if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology || DS2_ADM_COPP_TOPOLOGY_ID == topology) && (fdai->perf_mode == LEGACY_PCM_MODE) && - (msm_bedais[reg].compr_passthr_mode == - LEGACY_PCM)) + (passthr_mode == LEGACY_PCM)) msm_pcm_routing_deinit_pp( msm_bedais[reg].port_id, topology); msm_pcm_routing_build_matrix(val, session_type, path_type, - fdai->perf_mode); + fdai->perf_mode, + passthr_mode); } } if ((msm_bedais[reg].port_id == VOICE_RECORD_RX) @@ -1442,7 +1606,7 @@ static int msm_routing_get_audio_mixer(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions)) + if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions[0])) ucontrol->value.integer.value[0] = 1; else ucontrol->value.integer.value[0] = 0; @@ -1476,6 +1640,51 @@ static int msm_routing_put_audio_mixer(struct snd_kcontrol *kcontrol, return 1; } +static int msm_routing_get_listen_mixer(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + + if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions[0])) + ucontrol->value.integer.value[0] = 1; + else + ucontrol->value.integer.value[0] = 0; + + pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg, mc->shift, + ucontrol->value.integer.value[0]); + + return 0; +} + +static int msm_routing_put_listen_mixer(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget_list *wlist = + dapm_kcontrol_get_wlist(kcontrol); + struct snd_soc_dapm_widget *widget = wlist->widgets[0]; + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_dapm_update *update = NULL; + + pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg, mc->shift, + ucontrol->value.integer.value[0]); + + if (ucontrol->value.integer.value[0]) { + if (msm_pcm_routing_route_is_set(mc->reg, mc->shift) == false) + msm_pcm_routing_process_audio(mc->reg, mc->shift, 1); + snd_soc_dapm_mixer_update_power(widget->dapm, + kcontrol, 1, update); + } else if (!ucontrol->value.integer.value[0]) { + if (msm_pcm_routing_route_is_set(mc->reg, mc->shift) == true) + msm_pcm_routing_process_audio(mc->reg, mc->shift, 0); + snd_soc_dapm_mixer_update_power(widget->dapm, + kcontrol, 0, update); + } + + return 1; +} + static void msm_pcm_routing_process_voice(u16 reg, u16 val, int set) { u32 session_id = 0; @@ -1492,9 +1701,9 @@ static void msm_pcm_routing_process_voice(u16 reg, u16 val, int set) mutex_lock(&routing_lock); if (set) - set_bit(val, &msm_bedais[reg].fe_sessions); + set_bit(val, &msm_bedais[reg].fe_sessions[0]); else - clear_bit(val, &msm_bedais[reg].fe_sessions); + clear_bit(val, &msm_bedais[reg].fe_sessions[0]); if (val == MSM_FRONTEND_DAI_DTMF_RX && afe_get_port_type(msm_bedais[reg].port_id) == @@ -1553,7 +1762,7 @@ static int msm_routing_get_voice_mixer(struct snd_kcontrol *kcontrol, mutex_lock(&routing_lock); - if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions)) + if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions[0])) ucontrol->value.integer.value[0] = 1; else ucontrol->value.integer.value[0] = 0; @@ -1595,7 +1804,7 @@ static int msm_routing_get_voice_stub_mixer(struct snd_kcontrol *kcontrol, mutex_lock(&routing_lock); - if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions)) + if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions[0])) ucontrol->value.integer.value[0] = 1; else ucontrol->value.integer.value[0] = 0; @@ -1620,13 +1829,13 @@ static int msm_routing_put_voice_stub_mixer(struct snd_kcontrol *kcontrol, if (ucontrol->value.integer.value[0]) { mutex_lock(&routing_lock); - set_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions); + set_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions[0]); mutex_unlock(&routing_lock); snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, 1, update); } else { mutex_lock(&routing_lock); - clear_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions); + clear_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions[0]); mutex_unlock(&routing_lock); snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, 0, update); @@ -1928,23 +2137,19 @@ static int msm_routing_put_fm_pcmrx_switch_mixer(struct snd_kcontrol *kcontrol, return 1; } -static int msm_routing_lsm_mux_get(struct snd_kcontrol *kcontrol, +static int msm_routing_lsm_port_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - ucontrol->value.integer.value[0] = lsm_mux_slim_port; + ucontrol->value.integer.value[0] = lsm_port_index; return 0; } -static int msm_routing_lsm_mux_put(struct snd_kcontrol *kcontrol, +static int msm_routing_lsm_port_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = - dapm_kcontrol_get_wlist(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; int mux = ucontrol->value.enumerated.item[0]; int lsm_port = AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_TX; - struct snd_soc_dapm_update *update = NULL; if (mux >= e->items) { pr_err("%s: Invalid mux value %d\n", __func__, mux); @@ -1975,19 +2180,18 @@ static int msm_routing_lsm_mux_put(struct snd_kcontrol *kcontrol, case 7: lsm_port = AFE_PORT_ID_TERTIARY_MI2S_TX; break; + case 8: + lsm_port = AFE_PORT_ID_QUATERNARY_MI2S_TX; + break; + case 9: + lsm_port = ADM_LSM_PORT_ID; + break; default: pr_err("Default lsm port"); break; } set_lsm_port(lsm_port); - - if (ucontrol->value.integer.value[0]) { - lsm_mux_slim_port = ucontrol->value.integer.value[0]; - snd_soc_dapm_mux_update_power(widget->dapm, kcontrol, mux, e, update); - } else { - snd_soc_dapm_mux_update_power(widget->dapm, kcontrol, mux, e, update); - lsm_mux_slim_port = ucontrol->value.integer.value[0]; - } + lsm_port_index = ucontrol->value.integer.value[0]; return 0; } @@ -2000,23 +2204,27 @@ static int msm_routing_lsm_func_get(struct snd_kcontrol *kcontrol, enum afe_mad_type mad_type; pr_debug("%s: enter\n", __func__); - for (i = 0; i < ARRAY_SIZE(mad_audio_mux_text); i++) - if (!strncmp(kcontrol->id.name, mad_audio_mux_text[i], - strlen(mad_audio_mux_text[i]))) + for (i = 0; i < ARRAY_SIZE(lsm_port_text); i++) + if (!strnstr(kcontrol->id.name, lsm_port_text[i], + strlen(lsm_port_text[i]))) break; - if (i-- == ARRAY_SIZE(mad_audio_mux_text)) { + if (i-- == ARRAY_SIZE(lsm_port_text)) { WARN(1, "Invalid id name %s\n", kcontrol->id.name); return -EINVAL; } /*Check for Tertiary TX port*/ - if (!strcmp(kcontrol->id.name, mad_audio_mux_text[7])) { + if (!strcmp(kcontrol->id.name, lsm_port_text[7])) { ucontrol->value.integer.value[0] = MADSWAUDIO; return 0; } port_id = i * 2 + 1 + SLIMBUS_0_RX; + + if (!strcmp(kcontrol->id.name, lsm_port_text[8])) + port_id = AFE_PORT_ID_QUATERNARY_MI2S_TX; + mad_type = afe_port_get_mad_type(port_id); pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id, mad_type); @@ -2051,12 +2259,12 @@ static int msm_routing_lsm_func_put(struct snd_kcontrol *kcontrol, enum afe_mad_type mad_type; pr_debug("%s: enter\n", __func__); - for (i = 0; i < ARRAY_SIZE(mad_audio_mux_text); i++) - if (!strncmp(kcontrol->id.name, mad_audio_mux_text[i], - strlen(mad_audio_mux_text[i]))) + for (i = 0; i < ARRAY_SIZE(lsm_port_text); i++) + if (strnstr(kcontrol->id.name, lsm_port_text[i], + strlen(lsm_port_text[i]))) break; - if (i-- == ARRAY_SIZE(mad_audio_mux_text)) { + if (i-- == ARRAY_SIZE(lsm_port_text)) { WARN(1, "Invalid id name %s\n", kcontrol->id.name); return -EINVAL; } @@ -2084,11 +2292,16 @@ static int msm_routing_lsm_func_put(struct snd_kcontrol *kcontrol, } /*Check for Tertiary TX port*/ - if (!strcmp(kcontrol->id.name, mad_audio_mux_text[7])) { + if (strnstr(kcontrol->id.name, lsm_port_text[7], + strlen(lsm_port_text[7]))) { port_id = AFE_PORT_ID_TERTIARY_MI2S_TX; mad_type = MAD_SW_AUDIO; } + if (strnstr(kcontrol->id.name, lsm_port_text[8], + strlen(lsm_port_text[8]))) + port_id = AFE_PORT_ID_QUATERNARY_MI2S_TX; + pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id, mad_type); return afe_port_set_mad_type(port_id, mad_type); @@ -2253,6 +2466,144 @@ static int msm_routing_put_port_mixer(struct snd_kcontrol *kcontrol, return 1; } +static int msm_ec_ref_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = msm_ec_ref_ch; + pr_debug("%s: msm_ec_ref_ch = %ld\n", __func__, + ucontrol->value.integer.value[0]); + return 0; +} + +static int msm_ec_ref_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + msm_ec_ref_ch = ucontrol->value.integer.value[0]; + pr_debug("%s: msm_ec_ref_ch = %d\n", __func__, msm_ec_ref_ch); + adm_num_ec_ref_rx_chans(msm_ec_ref_ch); + return 0; +} + +static const char *const ec_ref_ch_text[] = {"Zero", "One", "Two", "Three", + "Four", "Five", "Six", "Seven", "Eight"}; + +static int msm_ec_ref_bit_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (msm_ec_ref_bit_format) { + case SNDRV_PCM_FORMAT_S24_LE: + ucontrol->value.integer.value[0] = 2; + break; + case SNDRV_PCM_FORMAT_S16_LE: + ucontrol->value.integer.value[0] = 1; + break; + default: + ucontrol->value.integer.value[0] = 0; + break; + } + pr_debug("%s: msm_ec_ref_bit_format = %ld\n", + __func__, ucontrol->value.integer.value[0]); + return 0; +} + +static int msm_ec_ref_bit_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u16 bit_width = 0; + + switch (ucontrol->value.integer.value[0]) { + case 2: + msm_ec_ref_bit_format = SNDRV_PCM_FORMAT_S24_LE; + break; + case 1: + msm_ec_ref_bit_format = SNDRV_PCM_FORMAT_S16_LE; + break; + default: + msm_ec_ref_bit_format = 0; + break; + } + + if (msm_ec_ref_bit_format == SNDRV_PCM_FORMAT_S16_LE) + bit_width = 16; + else if (msm_ec_ref_bit_format == SNDRV_PCM_FORMAT_S24_LE) + bit_width = 24; + + pr_debug("%s: msm_ec_ref_bit_format = %d\n", + __func__, msm_ec_ref_bit_format); + adm_ec_ref_rx_bit_width(bit_width); + return 0; +} + +static char const *ec_ref_bit_format_text[] = {"0", "S16_LE", "S24_LE"}; + +static int msm_ec_ref_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = msm_ec_ref_sampling_rate; + pr_debug("%s: msm_ec_ref_sampling_rate = %ld\n", + __func__, ucontrol->value.integer.value[0]); + return 0; +} + +static int msm_ec_ref_rate_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (ucontrol->value.integer.value[0]) { + case 0: + msm_ec_ref_sampling_rate = 0; + break; + case 1: + msm_ec_ref_sampling_rate = 8000; + break; + case 2: + msm_ec_ref_sampling_rate = 16000; + break; + case 3: + msm_ec_ref_sampling_rate = 32000; + break; + case 4: + msm_ec_ref_sampling_rate = 44100; + break; + case 5: + msm_ec_ref_sampling_rate = 48000; + break; + case 6: + msm_ec_ref_sampling_rate = 96000; + break; + case 7: + msm_ec_ref_sampling_rate = 192000; + break; + case 8: + msm_ec_ref_sampling_rate = 384000; + break; + default: + msm_ec_ref_sampling_rate = 48000; + break; + } + pr_debug("%s: msm_ec_ref_sampling_rate = %d\n", + __func__, msm_ec_ref_sampling_rate); + adm_ec_ref_rx_sampling_rate(msm_ec_ref_sampling_rate); + return 0; +} + +static const char *const ec_ref_rate_text[] = {"0", "8000", "16000", + "32000", "44100", "48000", "96000", "192000", "384000"}; + +static const struct soc_enum msm_route_ec_ref_params_enum[] = { + SOC_ENUM_SINGLE_EXT(9, ec_ref_ch_text), + SOC_ENUM_SINGLE_EXT(3, ec_ref_bit_format_text), + SOC_ENUM_SINGLE_EXT(9, ec_ref_rate_text), +}; + +static const struct snd_kcontrol_new ec_ref_param_controls[] = { + SOC_ENUM_EXT("EC Reference Channels", msm_route_ec_ref_params_enum[0], + msm_ec_ref_ch_get, msm_ec_ref_ch_put), + SOC_ENUM_EXT("EC Reference Bit Format", msm_route_ec_ref_params_enum[1], + msm_ec_ref_bit_format_get, msm_ec_ref_bit_format_put), + SOC_ENUM_EXT("EC Reference SampleRate", msm_route_ec_ref_params_enum[2], + msm_ec_ref_rate_get, msm_ec_ref_rate_put), +}; + static int msm_routing_ec_ref_rx_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -7721,6 +8072,198 @@ static const struct snd_kcontrol_new sec_mi2s_rx_port_mixer_controls[] = { msm_routing_put_port_mixer), }; +static const struct snd_kcontrol_new lsm1_mixer_controls[] = { + SOC_SINGLE_EXT("SLIMBUS_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, + MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX, + MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX, + MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX, + MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_5_TX", MSM_BACKEND_DAI_SLIMBUS_5_TX, + MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), +}; + +static const struct snd_kcontrol_new lsm2_mixer_controls[] = { + SOC_SINGLE_EXT("SLIMBUS_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, + MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX, + MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX, + MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX, + MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_5_TX", MSM_BACKEND_DAI_SLIMBUS_5_TX, + MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), +}; + +static const struct snd_kcontrol_new lsm3_mixer_controls[] = { + SOC_SINGLE_EXT("SLIMBUS_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, + MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX, + MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX, + MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX, + MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_5_TX", MSM_BACKEND_DAI_SLIMBUS_5_TX, + MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), +}; + +static const struct snd_kcontrol_new lsm4_mixer_controls[] = { + SOC_SINGLE_EXT("SLIMBUS_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, + MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX, + MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX, + MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX, + MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_5_TX", MSM_BACKEND_DAI_SLIMBUS_5_TX, + MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), +}; + +static const struct snd_kcontrol_new lsm5_mixer_controls[] = { + SOC_SINGLE_EXT("SLIMBUS_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, + MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX, + MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX, + MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX, + MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_5_TX", MSM_BACKEND_DAI_SLIMBUS_5_TX, + MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), +}; + +static const struct snd_kcontrol_new lsm6_mixer_controls[] = { + SOC_SINGLE_EXT("SLIMBUS_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, + MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX, + MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX, + MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX, + MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_5_TX", MSM_BACKEND_DAI_SLIMBUS_5_TX, + MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), +}; + +static const struct snd_kcontrol_new lsm7_mixer_controls[] = { + SOC_SINGLE_EXT("SLIMBUS_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, + MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX, + MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX, + MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX, + MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_5_TX", MSM_BACKEND_DAI_SLIMBUS_5_TX, + MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), +}; + +static const struct snd_kcontrol_new lsm8_mixer_controls[] = { + SOC_SINGLE_EXT("SLIMBUS_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, + MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX, + MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX, + MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX, + MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_5_TX", MSM_BACKEND_DAI_SLIMBUS_5_TX, + MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), +}; + static const struct snd_kcontrol_new slim_fm_switch_mixer_controls = SOC_SINGLE_EXT("Switch", SND_SOC_NOPM, 0, 1, 0, msm_routing_get_switch_mixer, @@ -7806,53 +8349,17 @@ static const struct snd_kcontrol_new usb_switch_mixer_controls = 0, 1, 0, msm_routing_get_usb_switch_mixer, msm_routing_put_usb_switch_mixer); -static const struct soc_enum lsm_mux_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mad_audio_mux_text), mad_audio_mux_text); - -static const struct snd_kcontrol_new lsm1_mux = - SOC_DAPM_ENUM_EXT("LSM1 MUX", lsm_mux_enum, - msm_routing_lsm_mux_get, - msm_routing_lsm_mux_put); - -static const struct snd_kcontrol_new lsm2_mux = - SOC_DAPM_ENUM_EXT("LSM2 MUX", lsm_mux_enum, - msm_routing_lsm_mux_get, - msm_routing_lsm_mux_put); -static const struct snd_kcontrol_new lsm3_mux = - SOC_DAPM_ENUM_EXT("LSM3 MUX", lsm_mux_enum, - msm_routing_lsm_mux_get, - msm_routing_lsm_mux_put); - -static const struct snd_kcontrol_new lsm4_mux = - SOC_DAPM_ENUM_EXT("LSM4 MUX", lsm_mux_enum, - msm_routing_lsm_mux_get, - msm_routing_lsm_mux_put); -static const struct snd_kcontrol_new lsm5_mux = - SOC_DAPM_ENUM_EXT("LSM5 MUX", lsm_mux_enum, - msm_routing_lsm_mux_get, - msm_routing_lsm_mux_put); - -static const struct snd_kcontrol_new lsm6_mux = - SOC_DAPM_ENUM_EXT("LSM6 MUX", lsm_mux_enum, - msm_routing_lsm_mux_get, - msm_routing_lsm_mux_put); -static const struct snd_kcontrol_new lsm7_mux = - SOC_DAPM_ENUM_EXT("LSM7 MUX", lsm_mux_enum, - msm_routing_lsm_mux_get, - msm_routing_lsm_mux_put); - -static const struct snd_kcontrol_new lsm8_mux = - SOC_DAPM_ENUM_EXT("LSM8 MUX", lsm_mux_enum, - msm_routing_lsm_mux_get, - msm_routing_lsm_mux_put); - +static const struct soc_enum lsm_port_enum = + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lsm_port_text), lsm_port_text); static const char * const lsm_func_text[] = { "None", "AUDIO", "BEACON", "ULTRASOUND", "SWAUDIO", }; static const struct soc_enum lsm_func_enum = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lsm_func_text), lsm_func_text); -static const struct snd_kcontrol_new lsm_function[] = { + +static const struct snd_kcontrol_new lsm_controls[] = { + /* kcontrol of lsm_function */ SOC_ENUM_EXT(SLIMBUS_0_TX_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum, msm_routing_lsm_func_get, msm_routing_lsm_func_put), SOC_ENUM_EXT(SLIMBUS_1_TX_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum, @@ -7867,6 +8374,33 @@ static const struct snd_kcontrol_new lsm_function[] = { msm_routing_lsm_func_get, msm_routing_lsm_func_put), SOC_ENUM_EXT(TERT_MI2S_TX_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum, msm_routing_lsm_func_get, msm_routing_lsm_func_put), + SOC_ENUM_EXT(QUAT_MI2S_TX_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum, + msm_routing_lsm_func_get, msm_routing_lsm_func_put), + /* kcontrol of lsm_port */ + SOC_ENUM_EXT("LSM1 Port", lsm_port_enum, + msm_routing_lsm_port_get, + msm_routing_lsm_port_put), + SOC_ENUM_EXT("LSM2 Port", lsm_port_enum, + msm_routing_lsm_port_get, + msm_routing_lsm_port_put), + SOC_ENUM_EXT("LSM3 Port", lsm_port_enum, + msm_routing_lsm_port_get, + msm_routing_lsm_port_put), + SOC_ENUM_EXT("LSM4 Port", lsm_port_enum, + msm_routing_lsm_port_get, + msm_routing_lsm_port_put), + SOC_ENUM_EXT("LSM5 Port", lsm_port_enum, + msm_routing_lsm_port_get, + msm_routing_lsm_port_put), + SOC_ENUM_EXT("LSM6 Port", lsm_port_enum, + msm_routing_lsm_port_get, + msm_routing_lsm_port_put), + SOC_ENUM_EXT("LSM7 Port", lsm_port_enum, + msm_routing_lsm_port_get, + msm_routing_lsm_port_put), + SOC_ENUM_EXT("LSM8 Port", lsm_port_enum, + msm_routing_lsm_port_get, + msm_routing_lsm_port_put), }; static const char * const aanc_slim_0_rx_text[] = { @@ -7923,7 +8457,7 @@ static int msm_routing_put_stereo_to_custom_stereo_control( (port_id != AFE_PORT_ID_INT4_MI2S_RX)) continue; - for_each_set_bit(i, &msm_bedais[be_index].fe_sessions, + for_each_set_bit(i, &msm_bedais[be_index].fe_sessions[0], MSM_FRONTEND_DAI_MM_SIZE) { if (fe_dai_map[i][SESSION_TYPE_RX].perf_mode != LEGACY_PCM_MODE) @@ -8029,6 +8563,45 @@ static const struct snd_kcontrol_new app_type_cfg_controls[] = { msm_routing_put_app_type_cfg_control), }; +static int msm_routing_get_lsm_app_type_cfg_control( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int msm_routing_put_lsm_app_type_cfg_control( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int i = 0, j; + int num_app_types = ucontrol->value.integer.value[i++]; + + memset(lsm_app_type_cfg, 0, MAX_APP_TYPES* + sizeof(struct msm_pcm_routing_app_type_data)); + if (num_app_types > MAX_APP_TYPES) { + pr_err("%s: number of app types exceed the max supported\n", + __func__); + return -EINVAL; + } + for (j = 0; j < num_app_types; j++) { + lsm_app_type_cfg[j].app_type = + ucontrol->value.integer.value[i++]; + lsm_app_type_cfg[j].sample_rate = + ucontrol->value.integer.value[i++]; + lsm_app_type_cfg[j].bit_width = + ucontrol->value.integer.value[i++]; + } + + return 0; +} + +static const struct snd_kcontrol_new lsm_app_type_cfg_controls[] = { + SOC_SINGLE_MULTI_EXT("Listen App Type Config", SND_SOC_NOPM, 0, + 0xFFFFFFFF, 0, 128, msm_routing_get_lsm_app_type_cfg_control, + msm_routing_put_lsm_app_type_cfg_control), +}; + static int msm_routing_get_use_ds1_or_ds2_control( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -8224,7 +8797,7 @@ static int msm_audio_get_copp_idx_from_port_id(int port_id, int session_type, goto done; } - for_each_set_bit(i, &msm_bedais[be_idx].fe_sessions, + for_each_set_bit(i, &msm_bedais[be_idx].fe_sessions[0], MSM_FRONTEND_DAI_MM_SIZE) { for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) { copp = session_copp_map[i] @@ -9298,16 +9871,6 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_SWITCH("USB_DL_HL", SND_SOC_NOPM, 0, 0, &usb_switch_mixer_controls), - /* Mux Definitions */ - SND_SOC_DAPM_MUX("LSM1 MUX", SND_SOC_NOPM, 0, 0, &lsm1_mux), - SND_SOC_DAPM_MUX("LSM2 MUX", SND_SOC_NOPM, 0, 0, &lsm2_mux), - SND_SOC_DAPM_MUX("LSM3 MUX", SND_SOC_NOPM, 0, 0, &lsm3_mux), - SND_SOC_DAPM_MUX("LSM4 MUX", SND_SOC_NOPM, 0, 0, &lsm4_mux), - SND_SOC_DAPM_MUX("LSM5 MUX", SND_SOC_NOPM, 0, 0, &lsm5_mux), - SND_SOC_DAPM_MUX("LSM6 MUX", SND_SOC_NOPM, 0, 0, &lsm6_mux), - SND_SOC_DAPM_MUX("LSM7 MUX", SND_SOC_NOPM, 0, 0, &lsm7_mux), - SND_SOC_DAPM_MUX("LSM8 MUX", SND_SOC_NOPM, 0, 0, &lsm8_mux), - /* Mixer definitions */ SND_SOC_DAPM_MIXER("PRI_RX Audio Mixer", SND_SOC_NOPM, 0, 0, pri_i2s_rx_mixer_controls, ARRAY_SIZE(pri_i2s_rx_mixer_controls)), @@ -9665,6 +10228,23 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_MIXER("USB_AUDIO_RX Port Mixer", SND_SOC_NOPM, 0, 0, usb_rx_port_mixer_controls, ARRAY_SIZE(usb_rx_port_mixer_controls)), + /* lsm mixer definitions */ + SND_SOC_DAPM_MIXER("LSM1 Mixer", SND_SOC_NOPM, 0, 0, + lsm1_mixer_controls, ARRAY_SIZE(lsm1_mixer_controls)), + SND_SOC_DAPM_MIXER("LSM2 Mixer", SND_SOC_NOPM, 0, 0, + lsm2_mixer_controls, ARRAY_SIZE(lsm2_mixer_controls)), + SND_SOC_DAPM_MIXER("LSM3 Mixer", SND_SOC_NOPM, 0, 0, + lsm3_mixer_controls, ARRAY_SIZE(lsm3_mixer_controls)), + SND_SOC_DAPM_MIXER("LSM4 Mixer", SND_SOC_NOPM, 0, 0, + lsm4_mixer_controls, ARRAY_SIZE(lsm4_mixer_controls)), + SND_SOC_DAPM_MIXER("LSM5 Mixer", SND_SOC_NOPM, 0, 0, + lsm5_mixer_controls, ARRAY_SIZE(lsm5_mixer_controls)), + SND_SOC_DAPM_MIXER("LSM6 Mixer", SND_SOC_NOPM, 0, 0, + lsm6_mixer_controls, ARRAY_SIZE(lsm6_mixer_controls)), + SND_SOC_DAPM_MIXER("LSM7 Mixer", SND_SOC_NOPM, 0, 0, + lsm7_mixer_controls, ARRAY_SIZE(lsm7_mixer_controls)), + SND_SOC_DAPM_MIXER("LSM8 Mixer", SND_SOC_NOPM, 0, 0, + lsm8_mixer_controls, ARRAY_SIZE(lsm8_mixer_controls)), /* Virtual Pins to force backends ON atm */ SND_SOC_DAPM_OUTPUT("BE_OUT"), SND_SOC_DAPM_INPUT("BE_IN"), @@ -11124,70 +11704,77 @@ static const struct snd_soc_dapm_route intercon[] = { {"SLIM4_UL_HL", NULL, "SLIMBUS_4_TX"}, {"SLIM8_UL_HL", NULL, "SLIMBUS_8_TX"}, - {"LSM1 MUX", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, - {"LSM1 MUX", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, - {"LSM1 MUX", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, - {"LSM1 MUX", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, - {"LSM1 MUX", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, - {"LSM1 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"}, - {"LSM1_UL_HL", NULL, "LSM1 MUX"}, - - {"LSM2 MUX", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, - {"LSM2 MUX", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, - {"LSM2 MUX", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, - {"LSM2 MUX", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, - {"LSM2 MUX", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, - {"LSM2 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"}, - {"LSM2_UL_HL", NULL, "LSM2 MUX"}, - - - {"LSM3 MUX", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, - {"LSM3 MUX", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, - {"LSM3 MUX", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, - {"LSM3 MUX", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, - {"LSM3 MUX", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, - {"LSM3 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"}, - {"LSM3_UL_HL", NULL, "LSM3 MUX"}, - - - {"LSM4 MUX", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, - {"LSM4 MUX", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, - {"LSM4 MUX", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, - {"LSM4 MUX", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, - {"LSM4 MUX", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, - {"LSM4 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"}, - {"LSM4_UL_HL", NULL, "LSM4 MUX"}, - - {"LSM5 MUX", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, - {"LSM5 MUX", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, - {"LSM5 MUX", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, - {"LSM5 MUX", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, - {"LSM5 MUX", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, - {"LSM5 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"}, - {"LSM5_UL_HL", NULL, "LSM5 MUX"}, - - {"LSM6 MUX", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, - {"LSM6 MUX", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, - {"LSM6 MUX", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, - {"LSM6 MUX", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, - {"LSM6 MUX", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, - {"LSM6_UL_HL", NULL, "LSM6 MUX"}, - - - {"LSM7 MUX", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, - {"LSM7 MUX", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, - {"LSM7 MUX", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, - {"LSM7 MUX", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, - {"LSM7 MUX", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, - {"LSM7_UL_HL", NULL, "LSM7 MUX"}, - - - {"LSM8 MUX", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, - {"LSM8 MUX", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, - {"LSM8 MUX", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, - {"LSM8 MUX", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, - {"LSM8 MUX", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, - {"LSM8_UL_HL", NULL, "LSM8 MUX"}, + + {"LSM1 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, + {"LSM1 Mixer", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, + {"LSM1 Mixer", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, + {"LSM1 Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, + {"LSM1 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, + {"LSM1 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"LSM1 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM1_UL_HL", NULL, "LSM1 Mixer"}, + + {"LSM2 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, + {"LSM2 Mixer", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, + {"LSM2 Mixer", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, + {"LSM2 Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, + {"LSM2 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, + {"LSM2 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"LSM2 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM2_UL_HL", NULL, "LSM2 Mixer"}, + + + {"LSM3 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, + {"LSM3 Mixer", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, + {"LSM3 Mixer", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, + {"LSM3 Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, + {"LSM3 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, + {"LSM3 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"LSM3 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM3_UL_HL", NULL, "LSM3 Mixer"}, + + + {"LSM4 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, + {"LSM4 Mixer", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, + {"LSM4 Mixer", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, + {"LSM4 Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, + {"LSM4 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, + {"LSM4 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"LSM4 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM4_UL_HL", NULL, "LSM4 Mixer"}, + + {"LSM5 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, + {"LSM5 Mixer", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, + {"LSM5 Mixer", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, + {"LSM5 Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, + {"LSM5 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, + {"LSM5 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"LSM5 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM5_UL_HL", NULL, "LSM5 Mixer"}, + + {"LSM6 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, + {"LSM6 Mixer", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, + {"LSM6 Mixer", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, + {"LSM6 Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, + {"LSM6 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, + {"LSM6 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM6_UL_HL", NULL, "LSM6 Mixer"}, + + {"LSM7 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, + {"LSM7 Mixer", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, + {"LSM7 Mixer", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, + {"LSM7 Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, + {"LSM7 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, + {"LSM7 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM7_UL_HL", NULL, "LSM7 Mixer"}, + + {"LSM8 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, + {"LSM8 Mixer", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, + {"LSM8 Mixer", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, + {"LSM8 Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, + {"LSM8 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, + {"LSM8 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM8_UL_HL", NULL, "LSM8 Mixer"}, {"CPE_LSM_UL_HL", NULL, "BE_IN"}, @@ -11804,7 +12391,9 @@ static int msm_pcm_routing_close(struct snd_pcm_substream *substream) path_type = ADM_PATH_LIVE_REC; mutex_lock(&routing_lock); - for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) { + for_each_set_bit(i, &bedai->fe_sessions[0], MSM_FRONTEND_DAI_MAX) { + if (!is_mm_lsm_fe_id(i)) + continue; fdai = &fe_dai_map[i][session_type]; if (fdai->strm_id != INVALID_SESSION) { int idx; @@ -11825,13 +12414,12 @@ static int msm_pcm_routing_close(struct snd_pcm_substream *substream) clear_bit(idx, &session_copp_map[i][session_type][be_id]); if ((fdai->perf_mode == LEGACY_PCM_MODE) && - (bedai->compr_passthr_mode == LEGACY_PCM)) + (bedai->passthr_mode == LEGACY_PCM)) msm_pcm_routing_deinit_pp(bedai->port_id, topology); } } - bedai->compr_passthr_mode = LEGACY_PCM; bedai->active = 0; bedai->sample_rate = 0; bedai->channel = 0; @@ -11851,6 +12439,7 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream) struct msm_pcm_routing_fdai_data *fdai; u32 session_id; struct media_format_info voc_be_media_format; + bool is_lsm; pr_debug("%s: substream->pcm->id:%s\n", __func__, substream->pcm->id); @@ -11863,7 +12452,7 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream) bedai = &msm_bedais[be_id]; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (bedai->compr_passthr_mode != LEGACY_PCM) + if (bedai->passthr_mode != LEGACY_PCM) path_type = ADM_PATH_COMPRESSED_RX; else path_type = ADM_PATH_PLAYBACK; @@ -11884,7 +12473,13 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream) */ bedai->active = 1; - for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) { + for_each_set_bit(i, &bedai->fe_sessions[0], MSM_FRONTEND_DAI_MAX) { + if (!(is_mm_lsm_fe_id(i) && + route_check_fe_id_adm_support(i))) + continue; + + is_lsm = (i >= MSM_FRONTEND_DAI_LSM1) && + (i <= MSM_FRONTEND_DAI_LSM8); fdai = &fe_dai_map[i][session_type]; if (fdai->strm_id != INVALID_SESSION) { int app_type, app_type_idx, copp_idx, acdb_dev_id; @@ -11906,7 +12501,15 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream) app_type = fe_dai_app_type_cfg[i][session_type].app_type; - if (app_type) { + if (app_type && is_lsm) { + app_type_idx = + msm_pcm_routing_get_lsm_app_type_idx(app_type); + sample_rate = + fe_dai_app_type_cfg[i][session_type]. + sample_rate; + bits_per_sample = + lsm_app_type_cfg[app_type_idx].bit_width; + } else if (app_type) { app_type_idx = msm_pcm_routing_get_app_type_idx(app_type); sample_rate = @@ -11951,16 +12554,16 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream) bedai->sample_rate); msm_pcm_routing_build_matrix(i, session_type, path_type, - fdai->perf_mode); + fdai->perf_mode, + bedai->passthr_mode); if ((fdai->perf_mode == LEGACY_PCM_MODE) && - (bedai->compr_passthr_mode == - LEGACY_PCM)) + (bedai->passthr_mode == LEGACY_PCM)) msm_pcm_routing_cfg_pp(bedai->port_id, copp_idx, topology, channels); } } - for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MAX) { + for_each_set_bit(i, &bedai->fe_sessions[0], MSM_FRONTEND_DAI_MAX) { session_id = msm_pcm_routing_get_voc_sessionid(i); if (session_id) { pr_debug("%s voice session_id: 0x%x\n", __func__, @@ -12025,6 +12628,7 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx) unsigned long pp_config = 0; bool mute_on; int latency; + bool compr_passthr_mode = true; pr_debug("%s: port_id %d, copp_idx %d\n", __func__, port_id, copp_idx); @@ -12061,14 +12665,16 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx) return -EINVAL; } + if ((msm_bedais[be_idx].passthr_mode == LEGACY_PCM) || + (msm_bedais[be_idx].passthr_mode == LISTEN)) + compr_passthr_mode = false; + pp_config = msm_bedais_pp_params[index].pp_params_config; if (test_bit(ADM_PP_PARAM_MUTE_BIT, &pp_config)) { pr_debug("%s: ADM_PP_PARAM_MUTE\n", __func__); clear_bit(ADM_PP_PARAM_MUTE_BIT, &pp_config); mute_on = msm_bedais_pp_params[index].mute_on; - if ((msm_bedais[be_idx].active) && - (msm_bedais[be_idx].compr_passthr_mode != - LEGACY_PCM)) + if ((msm_bedais[be_idx].active) && compr_passthr_mode) adm_send_compressed_device_mute(port_id, copp_idx, mute_on); @@ -12078,9 +12684,7 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx) clear_bit(ADM_PP_PARAM_LATENCY_BIT, &pp_config); latency = msm_bedais_pp_params[index].latency; - if ((msm_bedais[be_idx].active) && - (msm_bedais[be_idx].compr_passthr_mode != - LEGACY_PCM)) + if ((msm_bedais[be_idx].active) && compr_passthr_mode) adm_send_compressed_device_latency(port_id, copp_idx, latency); @@ -12096,6 +12700,7 @@ static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, int index, be_idx, i, topo_id, idx; bool mute; int latency; + bool compr_passthr_mode = true; pr_debug("%s: pp_id: 0x%x\n", __func__, pp_id); @@ -12120,7 +12725,11 @@ static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, return -EINVAL; } - for_each_set_bit(i, &msm_bedais[be_idx].fe_sessions, + if ((msm_bedais[be_idx].passthr_mode == LEGACY_PCM) || + (msm_bedais[be_idx].passthr_mode == LISTEN)) + compr_passthr_mode = false; + + for_each_set_bit(i, &msm_bedais[be_idx].fe_sessions[0], MSM_FRONTEND_DAI_MM_SIZE) { for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) { unsigned long copp = @@ -12134,7 +12743,7 @@ static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, continue; pr_debug("%s: port: 0x%x, copp %ld, be active: %d, passt: %d\n", __func__, port_id, copp, msm_bedais[be_idx].active, - msm_bedais[be_idx].compr_passthr_mode); + msm_bedais[be_idx].passthr_mode); switch (pp_id) { case ADM_PP_PARAM_MUTE_ID: pr_debug("%s: ADM_PP_PARAM_MUTE\n", __func__); @@ -12142,9 +12751,7 @@ static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, msm_bedais_pp_params[index].mute_on = mute; set_bit(ADM_PP_PARAM_MUTE_BIT, &msm_bedais_pp_params[index].pp_params_config); - if ((msm_bedais[be_idx].active) && - (msm_bedais[be_idx].compr_passthr_mode != - LEGACY_PCM)) + if ((msm_bedais[be_idx].active) && compr_passthr_mode) adm_send_compressed_device_mute(port_id, idx, mute); break; @@ -12156,9 +12763,7 @@ static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, &msm_bedais_pp_params[index].pp_params_config); latency = msm_bedais_pp_params[index].latency = ucontrol->value.integer.value[1]; - if ((msm_bedais[be_idx].active) && - (msm_bedais[be_idx].compr_passthr_mode != - LEGACY_PCM)) + if ((msm_bedais[be_idx].active) && compr_passthr_mode) adm_send_compressed_device_latency(port_id, idx, latency); break; @@ -12228,8 +12833,8 @@ static int msm_routing_probe(struct snd_soc_platform *platform) snd_soc_dapm_new_widgets(platform->component.dapm.card); - snd_soc_add_platform_controls(platform, lsm_function, - ARRAY_SIZE(lsm_function)); + snd_soc_add_platform_controls(platform, lsm_controls, + ARRAY_SIZE(lsm_controls)); snd_soc_add_platform_controls(platform, aanc_slim_0_rx_mux, ARRAY_SIZE(aanc_slim_0_rx_mux)); @@ -12240,10 +12845,16 @@ static int msm_routing_probe(struct snd_soc_platform *platform) snd_soc_add_platform_controls(platform, app_type_cfg_controls, ARRAY_SIZE(app_type_cfg_controls)); + snd_soc_add_platform_controls(platform, lsm_app_type_cfg_controls, + ARRAY_SIZE(lsm_app_type_cfg_controls)); + snd_soc_add_platform_controls(platform, stereo_to_custom_stereo_controls, ARRAY_SIZE(stereo_to_custom_stereo_controls)); + snd_soc_add_platform_controls(platform, ec_ref_param_controls, + ARRAY_SIZE(ec_ref_param_controls)); + msm_qti_pp_add_controls(platform); msm_dts_srs_tm_add_controls(platform); @@ -12326,7 +12937,7 @@ int msm_routing_check_backend_enabled(int fedai_id) return 0; } for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) { - if (test_bit(fedai_id, &msm_bedais[i].fe_sessions)) + if (test_bit(fedai_id, &msm_bedais[i].fe_sessions[0])) return msm_bedais[i].active; } return 0; diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h index 0bb069154512..a066e9afc9e5 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -392,6 +392,7 @@ enum { #define ADM_PP_PARAM_LATENCY_ID 1 #define ADM_PP_PARAM_LATENCY_BIT 2 #define BE_DAI_PORT_SESSIONS_IDX_MAX 4 +#define BE_DAI_FE_SESSIONS_IDX_MAX 2 struct msm_pcm_routing_evt { void (*event_func)(enum msm_pcm_routing_event, void *); @@ -401,7 +402,9 @@ struct msm_pcm_routing_evt { struct msm_pcm_routing_bdai_data { u16 port_id; /* AFE port ID */ u8 active; /* track if this backend is enabled */ - unsigned long fe_sessions; /* Front-end sessions */ + + /* Front-end sessions */ + unsigned long fe_sessions[BE_DAI_FE_SESSIONS_IDX_MAX]; /* * Track Tx BE ports -> Rx BE ports. * port_sessions[0] used to track BE 0 to BE 63. @@ -415,7 +418,7 @@ struct msm_pcm_routing_bdai_data { unsigned int channel; unsigned int format; unsigned int adm_override_ch; - u32 compr_passthr_mode; + u32 passthr_mode; char *name; }; diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c index 32826d38f65a..16ae05034662 100644 --- a/sound/soc/msm/qdsp6v2/q6adm.c +++ b/sound/soc/msm/qdsp6v2/q6adm.c @@ -2574,7 +2574,6 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, return copp_idx; } - void adm_copp_mfc_cfg(int port_id, int copp_idx, int dst_sample_rate) { struct audproc_mfc_output_media_fmt mfc_cfg; @@ -2677,8 +2676,43 @@ fail_cmd: return; } +static void route_set_opcode_matrix_id( + struct adm_cmd_matrix_map_routings_v5 **route_addr, + int path, uint32_t passthr_mode) +{ + struct adm_cmd_matrix_map_routings_v5 *route = *route_addr; -int adm_matrix_map(int path, struct route_payload payload_map, int perf_mode) + switch (path) { + case ADM_PATH_PLAYBACK: + route->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5; + route->matrix_id = ADM_MATRIX_ID_AUDIO_RX; + break; + case ADM_PATH_LIVE_REC: + if (passthr_mode == LISTEN) { + route->hdr.opcode = + ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5; + route->matrix_id = ADM_MATRIX_ID_LISTEN_TX; + break; + } + /* fall through to set matrix id for non-listen case */ + case ADM_PATH_NONLIVE_REC: + route->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5; + route->matrix_id = ADM_MATRIX_ID_AUDIO_TX; + break; + case ADM_PATH_COMPRESSED_RX: + route->hdr.opcode = ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5; + route->matrix_id = ADM_MATRIX_ID_COMPRESSED_AUDIO_RX; + break; + default: + pr_err("%s: Wrong path set[%d]\n", __func__, path); + break; + } + pr_debug("%s: opcode 0x%x, matrix id %d\n", + __func__, route->hdr.opcode, route->matrix_id); +} + +int adm_matrix_map(int path, struct route_payload payload_map, int perf_mode, + uint32_t passthr_mode) { struct adm_cmd_matrix_map_routings_v5 *route; struct adm_session_map_node_v5 *node; @@ -2711,32 +2745,9 @@ int adm_matrix_map(int path, struct route_payload payload_map, int perf_mode) route->hdr.dest_domain = APR_DOMAIN_ADSP; route->hdr.dest_port = 0; /* Ignored */; route->hdr.token = 0; - if (path == ADM_PATH_COMPRESSED_RX) { - pr_debug("%s: ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5 0x%x\n", - __func__, ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5); - route->hdr.opcode = ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5; - } else { - pr_debug("%s: DM_CMD_MATRIX_MAP_ROUTINGS_V5 0x%x\n", - __func__, ADM_CMD_MATRIX_MAP_ROUTINGS_V5); - route->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5; - } route->num_sessions = 1; + route_set_opcode_matrix_id(&route, path, passthr_mode); - switch (path) { - case ADM_PATH_PLAYBACK: - route->matrix_id = ADM_MATRIX_ID_AUDIO_RX; - break; - case ADM_PATH_LIVE_REC: - case ADM_PATH_NONLIVE_REC: - route->matrix_id = ADM_MATRIX_ID_AUDIO_TX; - break; - case ADM_PATH_COMPRESSED_RX: - route->matrix_id = ADM_MATRIX_ID_COMPRESSED_AUDIO_RX; - break; - default: - pr_err("%s: Wrong path set[%d]\n", __func__, path); - break; - } payload = ((u8 *)matrix_map + sizeof(struct adm_cmd_matrix_map_routings_v5)); node = (struct adm_session_map_node_v5 *)payload; diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 2c501ce3d6ff..74fbe984e6e9 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -8343,14 +8343,17 @@ int q6asm_get_apr_service_id(int session_id) int q6asm_get_asm_topology(int session_id) { - int topology; + int topology = -EINVAL; if (session_id <= 0 || session_id > ASM_ACTIVE_STREAMS_ALLOWED) { pr_err("%s: invalid session_id = %d\n", __func__, session_id); - topology = -EINVAL; goto done; } - + if (session[session_id] == NULL) { + pr_err("%s: session not created for session id = %d\n", + __func__, session_id); + goto done; + } topology = session[session_id]->topology; done: return topology; @@ -8358,14 +8361,17 @@ done: int q6asm_get_asm_app_type(int session_id) { - int app_type; + int app_type = -EINVAL; if (session_id <= 0 || session_id > ASM_ACTIVE_STREAMS_ALLOWED) { pr_err("%s: invalid session_id = %d\n", __func__, session_id); - app_type = -EINVAL; goto done; } - + if (session[session_id] == NULL) { + pr_err("%s: session not created for session id = %d\n", + __func__, session_id); + goto done; + } app_type = session[session_id]->app_type; done: return app_type; diff --git a/sound/soc/msm/qdsp6v2/q6lsm.c b/sound/soc/msm/qdsp6v2/q6lsm.c index 2bf0c490e834..525ec1c30f48 100644 --- a/sound/soc/msm/qdsp6v2/q6lsm.c +++ b/sound/soc/msm/qdsp6v2/q6lsm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, 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 @@ -38,6 +38,8 @@ #define LSM_ALIGN_BOUNDARY 512 #define LSM_SAMPLE_RATE 16000 #define QLSM_PARAM_ID_MINOR_VERSION 1 +#define QLSM_PARAM_ID_MINOR_VERSION_2 2 + static int lsm_afe_port; enum { @@ -707,29 +709,28 @@ static int q6lsm_send_confidence_levels( return rc; } -static int q6lsm_send_params(struct lsm_client *client, +static int q6lsm_send_param_opmode(struct lsm_client *client, struct lsm_module_param_ids *opmode_ids, - struct lsm_module_param_ids *connectport_ids, u32 set_param_opcode) { int rc; - struct lsm_cmd_set_opmode_connectport opmode_connectport; + struct lsm_cmd_set_params_opmode opmode_params; struct apr_hdr *msg_hdr; - struct lsm_param_connect_to_port *connect_to_port; + struct lsm_param_op_mode *op_mode; u32 data_payload_size, param_size; - msg_hdr = &opmode_connectport.msg_hdr; + msg_hdr = &opmode_params.msg_hdr; q6lsm_add_hdr(client, msg_hdr, - sizeof(opmode_connectport), true); + sizeof(opmode_params), true); msg_hdr->opcode = set_param_opcode; - data_payload_size = sizeof(opmode_connectport) - + data_payload_size = sizeof(opmode_params) - sizeof(*msg_hdr) - - sizeof(opmode_connectport.params_hdr); - q6lsm_set_param_hdr_info(&opmode_connectport.params_hdr, + sizeof(opmode_params.params_hdr); + q6lsm_set_param_hdr_info(&opmode_params.params_hdr, data_payload_size, 0, 0, 0); - connect_to_port = &opmode_connectport.connect_to_port; - op_mode = &opmode_connectport.op_mode; + op_mode = &opmode_params.op_mode; + param_size = sizeof(struct lsm_param_op_mode) - sizeof(op_mode->common); @@ -741,10 +742,61 @@ static int q6lsm_send_params(struct lsm_client *client, op_mode->reserved = 0; pr_debug("%s: mode = 0x%x", __func__, op_mode->mode); + rc = q6lsm_apr_send_pkt(client, client->apr, + &opmode_params, true, NULL); + if (rc) + pr_err("%s: Failed set_params opcode 0x%x, rc %d\n", + __func__, msg_hdr->opcode, rc); + + pr_debug("%s: leave %d\n", __func__, rc); + return rc; +} + +void set_lsm_port(int lsm_port) +{ + lsm_afe_port = lsm_port; +} + +int get_lsm_port(void) +{ + return lsm_afe_port; +} + +int q6lsm_set_port_connected(struct lsm_client *client) +{ + int rc; + struct lsm_cmd_set_connectport connectport; + struct lsm_module_param_ids connectport_ids; + struct apr_hdr *msg_hdr; + struct lsm_param_connect_to_port *connect_to_port; + u32 data_payload_size, param_size, set_param_opcode; + + if (client->use_topology) { + set_param_opcode = LSM_SESSION_CMD_SET_PARAMS_V2; + connectport_ids.module_id = LSM_MODULE_ID_FRAMEWORK; + connectport_ids.param_id = LSM_PARAM_ID_CONNECT_TO_PORT; + } else { + set_param_opcode = LSM_SESSION_CMD_SET_PARAMS; + connectport_ids.module_id = LSM_MODULE_ID_VOICE_WAKEUP; + connectport_ids.param_id = LSM_PARAM_ID_CONNECT_TO_PORT; + } + client->connect_to_port = get_lsm_port(); + + msg_hdr = &connectport.msg_hdr; + q6lsm_add_hdr(client, msg_hdr, + sizeof(connectport), true); + msg_hdr->opcode = set_param_opcode; + data_payload_size = sizeof(connectport) - + sizeof(*msg_hdr) - + sizeof(connectport.params_hdr); + q6lsm_set_param_hdr_info(&connectport.params_hdr, + data_payload_size, 0, 0, 0); + connect_to_port = &connectport.connect_to_port; + param_size = (sizeof(struct lsm_param_connect_to_port) - sizeof(connect_to_port->common)); q6lsm_set_param_common(&connect_to_port->common, - connectport_ids, param_size, + &connectport_ids, param_size, set_param_opcode); connect_to_port->minor_version = QLSM_PARAM_ID_MINOR_VERSION; connect_to_port->port_id = client->connect_to_port; @@ -752,23 +804,191 @@ static int q6lsm_send_params(struct lsm_client *client, pr_debug("%s: port= %d", __func__, connect_to_port->port_id); rc = q6lsm_apr_send_pkt(client, client->apr, - &opmode_connectport, true, NULL); + &connectport, true, NULL); + if (rc) + pr_err("%s: Failed set_params opcode 0x%x, rc %d\n", + __func__, msg_hdr->opcode, rc); + + return rc; +} +static int q6lsm_send_param_polling_enable(struct lsm_client *client, + bool poll_en, + struct lsm_module_param_ids *poll_enable_ids, + u32 set_param_opcode) +{ + int rc = 0; + struct lsm_cmd_poll_enable cmd; + struct apr_hdr *msg_hdr; + struct lsm_param_poll_enable *poll_enable; + u32 data_payload_size, param_size; + + msg_hdr = &cmd.msg_hdr; + q6lsm_add_hdr(client, msg_hdr, + sizeof(struct lsm_cmd_poll_enable), true); + msg_hdr->opcode = set_param_opcode; + data_payload_size = sizeof(struct lsm_cmd_poll_enable) - + sizeof(struct apr_hdr) - + sizeof(struct lsm_set_params_hdr); + q6lsm_set_param_hdr_info(&cmd.params_hdr, + data_payload_size, 0, 0, 0); + poll_enable = &cmd.poll_enable; + + param_size = (sizeof(struct lsm_param_poll_enable) - + sizeof(poll_enable->common)); + q6lsm_set_param_common(&poll_enable->common, + poll_enable_ids, param_size, + set_param_opcode); + poll_enable->minor_version = QLSM_PARAM_ID_MINOR_VERSION; + poll_enable->polling_enable = (poll_en) ? 1 : 0; + pr_debug("%s: poll enable= %d", __func__, poll_enable->polling_enable); + + rc = q6lsm_apr_send_pkt(client, client->apr, + &cmd, true, NULL); if (rc) pr_err("%s: Failed set_params opcode 0x%x, rc %d\n", __func__, msg_hdr->opcode, rc); - pr_debug("%s: leave %d\n", __func__, rc); return rc; } -void set_lsm_port(int lsm_port) +int q6lsm_set_fwk_mode_cfg(struct lsm_client *client, + uint32_t event_mode) { - lsm_afe_port = lsm_port; + int rc = 0; + struct lsm_cmd_set_fwk_mode_cfg cmd; + struct lsm_module_param_ids fwk_mode_cfg_ids; + struct apr_hdr *msg_hdr; + struct lsm_param_fwk_mode_cfg *fwk_mode_cfg; + u32 data_payload_size, param_size, set_param_opcode; + + if (client->use_topology) { + set_param_opcode = LSM_SESSION_CMD_SET_PARAMS_V2; + fwk_mode_cfg_ids.module_id = LSM_MODULE_ID_FRAMEWORK; + fwk_mode_cfg_ids.param_id = LSM_PARAM_ID_FWK_MODE_CONFIG; + } else { + pr_debug("%s: Ignore sending event mode\n", __func__); + return rc; + } + + msg_hdr = &cmd.msg_hdr; + q6lsm_add_hdr(client, msg_hdr, + sizeof(struct lsm_cmd_set_fwk_mode_cfg), true); + msg_hdr->opcode = set_param_opcode; + data_payload_size = sizeof(struct lsm_cmd_set_fwk_mode_cfg) - + sizeof(struct apr_hdr) - + sizeof(struct lsm_set_params_hdr); + q6lsm_set_param_hdr_info(&cmd.params_hdr, + data_payload_size, 0, 0, 0); + fwk_mode_cfg = &cmd.fwk_mode_cfg; + + param_size = (sizeof(struct lsm_param_fwk_mode_cfg) - + sizeof(fwk_mode_cfg->common)); + q6lsm_set_param_common(&fwk_mode_cfg->common, + &fwk_mode_cfg_ids, param_size, + set_param_opcode); + + fwk_mode_cfg->minor_version = QLSM_PARAM_ID_MINOR_VERSION; + fwk_mode_cfg->mode = event_mode; + pr_debug("%s: mode = %d\n", __func__, fwk_mode_cfg->mode); + + rc = q6lsm_apr_send_pkt(client, client->apr, + &cmd, true, NULL); + if (rc) + pr_err("%s: Failed set_params opcode 0x%x, rc %d\n", + __func__, msg_hdr->opcode, rc); + return rc; } -int get_lsm_port() +static int q6lsm_arrange_mch_map(struct lsm_param_media_fmt *media_fmt, + int channel_count) { - return lsm_afe_port; + int rc = 0; + + memset(media_fmt->channel_mapping, 0, LSM_MAX_NUM_CHANNELS); + + switch (channel_count) { + case 1: + media_fmt->channel_mapping[0] = PCM_CHANNEL_FC; + break; + case 2: + media_fmt->channel_mapping[0] = PCM_CHANNEL_FL; + media_fmt->channel_mapping[1] = PCM_CHANNEL_FR; + break; + case 3: + media_fmt->channel_mapping[0] = PCM_CHANNEL_FL; + media_fmt->channel_mapping[1] = PCM_CHANNEL_FR; + media_fmt->channel_mapping[2] = PCM_CHANNEL_FC; + break; + case 4: + media_fmt->channel_mapping[0] = PCM_CHANNEL_FL; + media_fmt->channel_mapping[1] = PCM_CHANNEL_FR; + media_fmt->channel_mapping[2] = PCM_CHANNEL_LS; + media_fmt->channel_mapping[3] = PCM_CHANNEL_RS; + break; + default: + pr_err("%s: invalid num_chan %d\n", __func__, channel_count); + rc = -EINVAL; + break; + } + return rc; +} + +int q6lsm_set_media_fmt_params(struct lsm_client *client) +{ + int rc = 0; + struct lsm_cmd_set_media_fmt cmd; + struct lsm_module_param_ids media_fmt_ids; + struct apr_hdr *msg_hdr; + struct lsm_param_media_fmt *media_fmt; + u32 data_payload_size, param_size, set_param_opcode; + struct lsm_hw_params param = client->hw_params; + + if (client->use_topology) { + set_param_opcode = LSM_SESSION_CMD_SET_PARAMS_V2; + media_fmt_ids.module_id = LSM_MODULE_ID_FRAMEWORK; + media_fmt_ids.param_id = LSM_PARAM_ID_MEDIA_FMT; + } else { + pr_debug("%s: Ignore sending media format\n", __func__); + goto err_ret; + } + + msg_hdr = &cmd.msg_hdr; + q6lsm_add_hdr(client, msg_hdr, + sizeof(struct lsm_cmd_set_media_fmt), true); + msg_hdr->opcode = set_param_opcode; + data_payload_size = sizeof(struct lsm_cmd_set_media_fmt) - + sizeof(struct apr_hdr) - + sizeof(struct lsm_set_params_hdr); + q6lsm_set_param_hdr_info(&cmd.params_hdr, + data_payload_size, 0, 0, 0); + media_fmt = &cmd.media_fmt; + + param_size = (sizeof(struct lsm_param_media_fmt) - + sizeof(media_fmt->common)); + q6lsm_set_param_common(&media_fmt->common, + &media_fmt_ids, param_size, + set_param_opcode); + + media_fmt->minor_version = QLSM_PARAM_ID_MINOR_VERSION_2; + media_fmt->sample_rate = param.sample_rate; + media_fmt->num_channels = param.num_chs; + media_fmt->bit_width = param.sample_size; + + rc = q6lsm_arrange_mch_map(media_fmt, media_fmt->num_channels); + if (rc) + goto err_ret; + + pr_debug("%s: sample rate= %d, channels %d bit width %d\n", + __func__, media_fmt->sample_rate, media_fmt->num_channels, + media_fmt->bit_width); + + rc = q6lsm_apr_send_pkt(client, client->apr, + &cmd, true, NULL); + if (rc) + pr_err("%s: Failed set_params opcode 0x%x, rc %d\n", + __func__, msg_hdr->opcode, rc); +err_ret: + return rc; } int q6lsm_set_data(struct lsm_client *client, @@ -776,7 +996,7 @@ int q6lsm_set_data(struct lsm_client *client, bool detectfailure) { int rc = 0; - struct lsm_module_param_ids opmode_ids, connectport_ids; + struct lsm_module_param_ids opmode_ids; struct lsm_module_param_ids conf_levels_ids; if (!client->confidence_levels) { @@ -800,16 +1020,12 @@ int q6lsm_set_data(struct lsm_client *client, goto err_ret; } client->mode |= detectfailure << 2; - client->connect_to_port = get_lsm_port(); opmode_ids.module_id = LSM_MODULE_ID_VOICE_WAKEUP; opmode_ids.param_id = LSM_PARAM_ID_OPERATION_MODE; - connectport_ids.module_id = LSM_MODULE_ID_VOICE_WAKEUP; - connectport_ids.param_id = LSM_PARAM_ID_CONNECT_TO_PORT; - - rc = q6lsm_send_params(client, &opmode_ids, &connectport_ids, - LSM_SESSION_CMD_SET_PARAMS); + rc = q6lsm_send_param_opmode(client, &opmode_ids, + LSM_SESSION_CMD_SET_PARAMS); if (rc) { pr_err("%s: Failed to set lsm config params %d\n", __func__, rc); @@ -1390,7 +1606,7 @@ static int q6lsm_send_param_gain( int q6lsm_set_one_param(struct lsm_client *client, struct lsm_params_info *p_info, void *data, - enum LSM_PARAM_TYPE param_type) + uint32_t param_type) { int rc = 0, pkt_sz; struct lsm_module_param_ids ids; @@ -1409,7 +1625,6 @@ int q6lsm_set_one_param(struct lsm_client *client, case LSM_OPERATION_MODE: { struct snd_lsm_detect_mode *det_mode = data; struct lsm_module_param_ids opmode_ids; - struct lsm_module_param_ids connectport_ids; if (det_mode->mode == LSM_MODE_KEYWORD_ONLY_DETECTION) { client->mode = 0x01; @@ -1422,16 +1637,12 @@ int q6lsm_set_one_param(struct lsm_client *client, } client->mode |= det_mode->detect_failure << 2; - client->connect_to_port = get_lsm_port(); opmode_ids.module_id = p_info->module_id; opmode_ids.param_id = p_info->param_id; - connectport_ids.module_id = LSM_MODULE_ID_FRAMEWORK; - connectport_ids.param_id = LSM_PARAM_ID_CONNECT_TO_PORT; - - rc = q6lsm_send_params(client, &opmode_ids, &connectport_ids, - LSM_SESSION_CMD_SET_PARAMS_V2); + rc = q6lsm_send_param_opmode(client, &opmode_ids, + LSM_SESSION_CMD_SET_PARAMS_V2); if (rc) pr_err("%s: OPERATION_MODE failed, rc %d\n", __func__, rc); @@ -1458,6 +1669,20 @@ int q6lsm_set_one_param(struct lsm_client *client, pr_err("%s: CONFIDENCE_LEVELS cmd failed, rc %d\n", __func__, rc); break; + case LSM_POLLING_ENABLE: { + struct snd_lsm_poll_enable *lsm_poll_enable = + (struct snd_lsm_poll_enable *) data; + ids.module_id = p_info->module_id; + ids.param_id = p_info->param_id; + rc = q6lsm_send_param_polling_enable(client, + lsm_poll_enable->poll_en, &ids, + LSM_SESSION_CMD_SET_PARAMS_V2); + if (rc) + pr_err("%s: POLLING ENABLE cmd failed, rc %d\n", + __func__, rc); + break; + } + case LSM_REG_SND_MODEL: { struct lsm_cmd_set_params model_param; u32 payload_size; diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c index e7619c0ca0dd..d352133b7c32 100644 --- a/sound/soc/msm/qdsp6v2/q6voice.c +++ b/sound/soc/msm/qdsp6v2/q6voice.c @@ -3990,6 +3990,10 @@ static int voice_send_cvp_media_fmt_info_cmd(struct voice_data *v) { int ret; + ret = voice_send_cvp_device_channels_cmd(v); + if (ret < 0) + goto done; + if (voice_get_cvd_int_version(common.cvd_version) >= CVD_INT_VERSION_2_3) { ret = voice_send_cvp_media_format_cmd(v, RX_PATH); @@ -4002,8 +4006,6 @@ static int voice_send_cvp_media_fmt_info_cmd(struct voice_data *v) if (common.ec_ref_ext) ret = voice_send_cvp_media_format_cmd(v, EC_REF_PATH); - } else { - ret = voice_send_cvp_device_channels_cmd(v); } done: |
