diff options
57 files changed, 1662 insertions, 246 deletions
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt index 38e056cdc0ee..db21a2b58c2b 100644 --- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt +++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt @@ -1311,6 +1311,13 @@ Optional properties: - pinctrl-x: Defines pinctrl state for each pin group. + - qcom,msm-cpudai-tdm-clk-attribute: Clock attribute for tdm. + 0 - Clk invalid attribute + 1 - Clk attribute couple no + 2 - Clk attribute couple dividend + 3 - Clk attribute couple divisor + 4 - Clk attribute invert couple no + Example: qcom,msm-dai-tdm-quat-rx { diff --git a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi index a4c08f19dfa0..9dbec1e87fda 100644 --- a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi @@ -547,7 +547,7 @@ #include "msm8996-sde-display.dtsi" -&mdss_mdp { +&sde_kms { qcom,mdss-pref-prim-intf = "dsi"; qcom,sde-plane-id-map { qcom,sde-plane-id@0 { @@ -1241,7 +1241,7 @@ qcom,vin-sel = <2>; /* 1.8 */ qcom,out-strength = <1>; qcom,src-sel = <0>; /* GPIO */ - qcom,master-en = <0>; /* Disable GPIO */ + qcom,master-en = <1>; /* Enable GPIO */ status = "okay"; }; diff --git a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi index 91cfa5826519..ad14bfd00cd1 100644 --- a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi @@ -333,7 +333,7 @@ }; }; -&mdss_mdp { +&sde_kms { qcom,mdss-pref-prim-intf = "dsi"; qcom,sde-plane-id-map { qcom,sde-plane-id@0 { diff --git a/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi index ab10a71d1fd7..0bd9b02f3d2e 100644 --- a/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -343,7 +343,7 @@ qcom,mdss-pref-prim-intf = "dsi"; }; -&mdss_hdmi { +&sde_hdmi { status = "ok"; }; diff --git a/arch/arm/boot/dts/qcom/msm8996-sde-display.dtsi b/arch/arm/boot/dts/qcom/msm8996-sde-display.dtsi index 061301f1c479..1c81bc433374 100644 --- a/arch/arm/boot/dts/qcom/msm8996-sde-display.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-sde-display.dtsi @@ -94,8 +94,8 @@ label = "dsi_dual_sharp_video"; qcom,display-type = "primary"; - qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>; - qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>; + qcom,dsi-ctrl = <&sde_dsi0 &sde_dsi1>; + qcom,dsi-phy = <&sde_dsi_phy0 &sde_dsi_phy1>; clocks = <&clock_mmss clk_ext_byte0_clk_src>, <&clock_mmss clk_ext_pclk0_clk_src>; clock-names = "src_byte_clk", "src_pixel_clk"; @@ -118,8 +118,8 @@ label = "single_dsi_sim"; qcom,display-type = "primary"; - qcom,dsi-ctrl = <&mdss_dsi0>; - qcom,dsi-phy = <&mdss_dsi_phy0>; + qcom,dsi-ctrl = <&sde_dsi0>; + qcom,dsi-phy = <&sde_dsi_phy0>; clocks = <&clock_mmss clk_ext_byte0_clk_src>, <&clock_mmss clk_ext_pclk0_clk_src>; clock-names = "src_byte_clk", "src_pixel_clk"; @@ -140,8 +140,8 @@ label = "single_dsi_toshiba_720p"; qcom,display-type = "primary"; - qcom,dsi-ctrl = <&mdss_dsi0>; - qcom,dsi-phy = <&mdss_dsi_phy0>; + qcom,dsi-ctrl = <&sde_dsi0>; + qcom,dsi-phy = <&sde_dsi_phy0>; clocks = <&clock_mmss clk_ext_byte0_clk_src>, <&clock_mmss clk_ext_pclk0_clk_src>; clock-names = "src_byte_clk", "src_pixel_clk"; @@ -161,8 +161,8 @@ label = "single_dsi_jdi_1080p"; qcom,display-type = "primary"; - qcom,dsi-ctrl = <&mdss_dsi0>; - qcom,dsi-phy = <&mdss_dsi_phy0>; + qcom,dsi-ctrl = <&sde_dsi0>; + qcom,dsi-phy = <&sde_dsi_phy0>; clocks = <&clock_mmss clk_ext_byte0_clk_src>, <&clock_mmss clk_ext_pclk0_clk_src>; clock-names = "src_byte_clk", "src_pixel_clk"; @@ -180,8 +180,8 @@ label = "single_dsi_sharp_1080p"; qcom,display-type = "primary"; - qcom,dsi-ctrl = <&mdss_dsi0>; - qcom,dsi-phy = <&mdss_dsi_phy0>; + qcom,dsi-ctrl = <&sde_dsi0>; + qcom,dsi-phy = <&sde_dsi_phy0>; clocks = <&clock_mmss clk_ext_byte0_clk_src>, <&clock_mmss clk_ext_pclk0_clk_src>; clock-names = "src_byte_clk", "src_pixel_clk"; @@ -209,8 +209,8 @@ qcom,display-type = "primary"; /* dsi1/dsi0 swapped due to IMGSWAP */ - qcom,dsi-ctrl = <&mdss_dsi1 &mdss_dsi0>; - qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>; + qcom,dsi-ctrl = <&sde_dsi1 &sde_dsi0>; + qcom,dsi-phy = <&sde_dsi_phy0 &sde_dsi_phy1>; clocks = <&clock_mmss clk_ext_byte0_clk_src>, <&clock_mmss clk_ext_pclk0_clk_src>; clock-names = "src_byte_clk", "src_pixel_clk"; @@ -231,8 +231,8 @@ label = "dsi_dual_nt35597_video"; qcom,display-type = "primary"; - qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>; - qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>; + qcom,dsi-ctrl = <&sde_dsi0 &sde_dsi1>; + qcom,dsi-phy = <&sde_dsi_phy0 &sde_dsi_phy1>; clocks = <&clock_mmss clk_ext_byte0_clk_src>, <&clock_mmss clk_ext_pclk0_clk_src>; clock-names = "src_byte_clk", "src_pixel_clk"; @@ -253,8 +253,8 @@ label = "dsi_adv_7533_1"; qcom,display-type = "secondary"; - qcom,dsi-ctrl = <&mdss_dsi0>; - qcom,dsi-phy = <&mdss_dsi_phy0>; + qcom,dsi-ctrl = <&sde_dsi0>; + qcom,dsi-phy = <&sde_dsi_phy0>; clocks = <&clock_mmss clk_ext_byte0_clk_src>, <&clock_mmss clk_ext_pclk0_clk_src>; clock-names = "src_byte_clk", "src_pixel_clk"; @@ -269,8 +269,8 @@ label = "dsi_adv_7533_2"; qcom,display-type = "tertiary"; - qcom,dsi-ctrl = <&mdss_dsi1>; - qcom,dsi-phy = <&mdss_dsi_phy1>; + qcom,dsi-ctrl = <&sde_dsi1>; + qcom,dsi-phy = <&sde_dsi_phy1>; clocks = <&clock_mmss clk_ext_byte1_clk_src>, <&clock_mmss clk_ext_pclk1_clk_src>; clock-names = "src_byte_clk", "src_pixel_clk"; @@ -297,8 +297,8 @@ }; }; -&mdss_mdp { - connectors = <&mdss_hdmi &sde_hdmi &dsi_adv_7533_1 &dsi_adv_7533_2>; +&sde_kms { + connectors = <&sde_hdmi_tx &sde_hdmi &dsi_adv_7533_1 &dsi_adv_7533_2>; }; &dsi_dual_sharp_video { diff --git a/arch/arm/boot/dts/qcom/msm8996-sde.dtsi b/arch/arm/boot/dts/qcom/msm8996-sde.dtsi index f0fa5dcb2224..6d0e5c4cb920 100644 --- a/arch/arm/boot/dts/qcom/msm8996-sde.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-sde.dtsi @@ -11,7 +11,7 @@ */ &soc { - mdss_mdp: qcom,mdss_mdp@900000 { + sde_kms: qcom,sde_kms@900000 { compatible = "qcom,sde-kms"; reg = <0x00900000 0x90000>, <0x009b0000 0x1040>, @@ -180,8 +180,8 @@ }; }; - smmu_mdp_unsec: qcom,smmu_mdp_unsec_cb { - compatible = "qcom,smmu_mdp_unsec"; + smmu_kms_unsec: qcom,smmu_kms_unsec_cb { + compatible = "qcom,smmu_kms_unsec"; iommus = <&mdp_smmu 0>; }; @@ -211,7 +211,7 @@ }; }; - mdss_dsi0: qcom,mdss_dsi_ctrl0@994000 { + sde_dsi0: qcom,sde_dsi_ctrl0@994000 { compatible = "qcom,dsi-ctrl-hw-v1.4"; label = "dsi-ctrl-0"; cell-index = <0>; @@ -246,7 +246,7 @@ <22 512 0 0>, <22 512 0 1000>; - interrupt-parent = <&mdss_mdp>; + interrupt-parent = <&sde_kms>; interrupts = <4 0>; qcom,core-supply-entries { #address-cells = <1>; @@ -287,7 +287,7 @@ }; }; - mdss_dsi1: qcom,mdss_dsi_ctrl1@996000 { + sde_dsi1: qcom,sde_dsi_ctrl1@996000 { compatible = "qcom,dsi-ctrl-hw-v1.4"; label = "dsi-ctrl-1"; cell-index = <1>; @@ -321,7 +321,7 @@ <22 512 0 0>, <22 512 0 1000>; - interrupt-parent = <&mdss_mdp>; + interrupt-parent = <&sde_kms>; interrupts = <5 0>; qcom,core-supply-entries { #address-cells = <1>; @@ -361,7 +361,7 @@ }; }; - mdss_dsi_phy0: qcom,mdss_dsi_phy0@994400 { + sde_dsi_phy0: qcom,sde_dsi_phy0@994400 { compatible = "qcom,dsi-phy-v4.0"; label = "dsi-phy-0"; cell-index = <0>; @@ -420,7 +420,7 @@ }; }; - mdss_dsi_phy1: qcom,mdss_dsi_phy1@996400 { + sde_dsi_phy1: qcom,sde_dsi_phy1@996400 { compatible = "qcom,dsi-phy-v4.0"; label = "dsi-phy-1"; cell-index = <1>; @@ -479,7 +479,7 @@ }; }; - mdss_hdmi: qcom,hdmi_tx@9a0000 { + sde_hdmi_tx: qcom,hdmi_tx_8996@9a0000 { compatible = "qcom,hdmi-tx-8996"; reg = <0x009a0000 0x50c>, @@ -499,7 +499,7 @@ "core_clk", "alt_iface_clk", "extp_clk"; - interrupt-parent = <&mdss_mdp>; + interrupt-parent = <&sde_kms>; interrupts = <8 0>; hpd-gdsc-supply = <&gdsc_mdss>; qcom,hdmi-tx-hpd-gpio = <&pm8994_mpps 4 0>; @@ -511,23 +511,8 @@ &mdss_hdmi_ddc_suspend &mdss_hdmi_cec_suspend>; - hdmi_audio: qcom,msm-hdmi-audio-rx { + sde_hdmi_audio: qcom,sde-hdmi-audio-rx { compatible = "qcom,msm-hdmi-audio-codec-rx"; }; }; }; - -/* dummy nodes for compatibility with 8996 mdss dtsi */ -&soc { - mdss_dsi: qcom,mdss_dsi_dummy { - /* dummy node for backward compatibility */ - }; - - mdss_hdmi_tx: qcom,mdss_hdmi_tx_dummy { - /* dummy node for backward compatibility */ - }; - - mdss_fb2: qcom,mdss_fb2_dummy { - /* dummy node for backward compatibility */ - }; -}; diff --git a/arch/arm/boot/dts/qcom/msm8996-v2.dtsi b/arch/arm/boot/dts/qcom/msm8996-v2.dtsi index 9725bc3ee530..698c0193a164 100644 --- a/arch/arm/boot/dts/qcom/msm8996-v2.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-v2.dtsi @@ -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 @@ -480,7 +480,7 @@ gdsc-venus-supply = <&gdsc_venus>; }; -&mdss_hdmi { +&sde_hdmi_tx { hpd-gdsc-venus-supply = <&gdsc_venus>; }; diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi index 80b3437beac6..dcd884b4a745 100644 --- a/arch/arm/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996.dtsi @@ -242,6 +242,7 @@ #include "msm8996-ion.dtsi" #include "msm8996-sde.dtsi" +#include "msm8996-mdss.dtsi" #include "msm8996-mdss-pll.dtsi" #include "msm8996-smp2p.dtsi" #include "msm8996-ipcrouter.dtsi" diff --git a/arch/arm/boot/dts/qcom/msm8996v3-auto.dtsi b/arch/arm/boot/dts/qcom/msm8996v3-auto.dtsi index 32adb9a36dd4..355062adf7ef 100644 --- a/arch/arm/boot/dts/qcom/msm8996v3-auto.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996v3-auto.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016 - 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -167,3 +167,40 @@ < 560000000 7 >, < 624000000 7 >; }; + +&soc { + ipa_hw: qcom,ipa@680000 { + compatible = "qcom,ipa"; + reg = <0x680000 0x4effc>, + <0x684000 0x26934>; + reg-names = "ipa-base", "bam-base"; + interrupts = <0 333 0>, + <0 432 0>; + interrupt-names = "ipa-irq", "bam-irq"; + qcom,ipa-hw-ver = <5>; /* IPA core version = IPAv2.5 */ + qcom,ipa-hw-mode = <0>; + qcom,ee = <0>; + qcom,use-ipa-tethering-bridge; + qcom,ipa-bam-remote-mode; + qcom,modem-cfg-emb-pipe-flt; + clocks = <&clock_gcc clk_ipa_clk>; + clock-names = "core_clk"; + qcom,use-dma-zone; + qcom,msm-bus,name = "ipa"; + qcom,msm-bus,num-cases = <3>; + qcom,msm-bus,num-paths = <2>; + qcom,msm-bus,vectors-KBps = + <90 512 0 0>, <90 585 0 0>, /* No vote */ + <90 512 80000 640000>, <90 585 80000 640000>, /* SVS */ + <90 512 206000 960000>, <90 585 206000 960000>; /* PERF */ + qcom,bus-vector-names = "MIN", "SVS", "PERF"; + }; + + qcom,rmnet-ipa { + compatible = "qcom,rmnet-ipa"; + qcom,rmnet-ipa-ssr; + qcom,ipa-loaduC; + qcom,ipa-advertise-sg-support; + }; +}; + diff --git a/arch/arm/boot/dts/qcom/sdm630.dtsi b/arch/arm/boot/dts/qcom/sdm630.dtsi index 8ca0b94403cb..cff3aa809488 100644 --- a/arch/arm/boot/dts/qcom/sdm630.dtsi +++ b/arch/arm/boot/dts/qcom/sdm630.dtsi @@ -1689,6 +1689,7 @@ qcom,vdd-1.3-rfa-config = <1200000 1370000>; qcom,vdd-3.3-ch0-config = <3200000 3400000>; qcom,wlan-msa-memory = <0x100000>; + qcom,wlan-msa-fixed-region = <&wlan_msa_mem>; qcom,smmu-s1-bypass; }; diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi index 8158825264c2..f14c9a32c2f9 100644 --- a/arch/arm/boot/dts/qcom/sdm660.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660.dtsi @@ -1940,6 +1940,7 @@ qcom,vdd-1.3-rfa-config = <1200000 1370000>; qcom,vdd-3.3-ch0-config = <3200000 3400000>; qcom,wlan-msa-memory = <0x100000>; + qcom,wlan-msa-fixed-region = <&wlan_msa_mem>; qcom,smmu-s1-bypass; }; diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 13016f32b344..a84172106e0f 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -212,6 +212,7 @@ struct fastrpc_channel_ctx { struct device *dev; struct fastrpc_session_ctx session[NUM_SESSIONS]; struct completion work; + struct completion workport; struct notifier_block nb; struct kref kref; int channel; @@ -1474,6 +1475,7 @@ static void fastrpc_init(struct fastrpc_apps *me) me->channel = &gcinfo[0]; for (i = 0; i < NUM_CHANNELS; i++) { init_completion(&me->channel[i].work); + init_completion(&me->channel[i].workport); me->channel[i].sesscount = 0; } } @@ -2135,7 +2137,7 @@ void fastrpc_glink_notify_state(void *handle, const void *priv, unsigned event) switch (event) { case GLINK_CONNECTED: link->port_state = FASTRPC_LINK_CONNECTED; - complete(&me->channel[cid].work); + complete(&me->channel[cid].workport); break; case GLINK_LOCAL_DISCONNECTED: link->port_state = FASTRPC_LINK_DISCONNECTED; @@ -2285,8 +2287,7 @@ static void fastrpc_glink_close(void *chan, int cid) return; link = &gfa.channel[cid].link; - if (link->port_state == FASTRPC_LINK_CONNECTED || - link->port_state == FASTRPC_LINK_CONNECTING) { + if (link->port_state == FASTRPC_LINK_CONNECTED) { link->port_state = FASTRPC_LINK_DISCONNECTING; glink_close(chan); } @@ -2484,8 +2485,9 @@ static int fastrpc_channel_open(struct fastrpc_file *fl) if (err) goto bail; - VERIFY(err, wait_for_completion_timeout(&me->channel[cid].work, - RPC_TIMEOUT)); + VERIFY(err, + wait_for_completion_timeout(&me->channel[cid].workport, + RPC_TIMEOUT)); if (err) { me->channel[cid].chan = 0; goto bail; diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c index 20e617ed0770..e37609abf7bf 100644 --- a/drivers/char/diag/diag_masks.c +++ b/drivers/char/diag/diag_masks.c @@ -796,7 +796,9 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len, for (i = 0; i < NUM_PERIPHERALS; i++) { if (!diag_check_update(i)) continue; + mutex_lock(&driver->md_session_lock); diag_send_msg_mask_update(i, req->ssid_first, req->ssid_last); + mutex_unlock(&driver->md_session_lock); } end: return write_len; @@ -856,7 +858,9 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len, for (i = 0; i < NUM_PERIPHERALS; i++) { if (!diag_check_update(i)) continue; + mutex_lock(&driver->md_session_lock); diag_send_msg_mask_update(i, ALL_SSID, ALL_SSID); + mutex_unlock(&driver->md_session_lock); } return write_len; @@ -950,7 +954,9 @@ static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len, for (i = 0; i < NUM_PERIPHERALS; i++) { if (!diag_check_update(i)) continue; + mutex_lock(&driver->md_session_lock); diag_send_event_mask_update(i); + mutex_unlock(&driver->md_session_lock); } return write_len; @@ -997,7 +1003,9 @@ static int diag_cmd_toggle_events(unsigned char *src_buf, int src_len, for (i = 0; i < NUM_PERIPHERALS; i++) { if (!diag_check_update(i)) continue; + mutex_lock(&driver->md_session_lock); diag_send_event_mask_update(i); + mutex_unlock(&driver->md_session_lock); } memcpy(dest_buf, &header, sizeof(header)); write_len += sizeof(header); @@ -1251,7 +1259,9 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len, for (i = 0; i < NUM_PERIPHERALS; i++) { if (!diag_check_update(i)) continue; + mutex_lock(&driver->md_session_lock); diag_send_log_mask_update(i, req->equip_id); + mutex_unlock(&driver->md_session_lock); } end: return write_len; @@ -1302,7 +1312,9 @@ static int diag_cmd_disable_log_mask(unsigned char *src_buf, int src_len, for (i = 0; i < NUM_PERIPHERALS; i++) { if (!diag_check_update(i)) continue; + mutex_lock(&driver->md_session_lock); diag_send_log_mask_update(i, ALL_EQUIP_ID); + mutex_unlock(&driver->md_session_lock); } return write_len; @@ -1966,9 +1978,11 @@ void diag_send_updates_peripheral(uint8_t peripheral) diag_send_feature_mask_update(peripheral); if (driver->time_sync_enabled) diag_send_time_sync_update(peripheral); + mutex_lock(&driver->md_session_lock); diag_send_msg_mask_update(peripheral, ALL_SSID, ALL_SSID); diag_send_log_mask_update(peripheral, ALL_EQUIP_ID); diag_send_event_mask_update(peripheral); + mutex_unlock(&driver->md_session_lock); diag_send_real_time_update(peripheral, driver->real_time_mode[DIAG_LOCAL_PROC]); diag_send_peripheral_buffering_mode( diff --git a/drivers/char/diag/diag_memorydevice.c b/drivers/char/diag/diag_memorydevice.c index 06b83f5230bf..a27f12883c8d 100644 --- a/drivers/char/diag/diag_memorydevice.c +++ b/drivers/char/diag/diag_memorydevice.c @@ -129,37 +129,6 @@ void diag_md_close_all() diag_ws_reset(DIAG_WS_MUX); } -static int diag_md_get_peripheral(int ctxt) -{ - int peripheral; - - if (driver->num_pd_session) { - peripheral = GET_PD_CTXT(ctxt); - switch (peripheral) { - case UPD_WLAN: - case UPD_AUDIO: - case UPD_SENSORS: - break; - case DIAG_ID_MPSS: - case DIAG_ID_LPASS: - case DIAG_ID_CDSP: - default: - peripheral = - GET_BUF_PERIPHERAL(ctxt); - if (peripheral > NUM_PERIPHERALS) - peripheral = -EINVAL; - break; - } - } else { - /* Account for Apps data as well */ - peripheral = GET_BUF_PERIPHERAL(ctxt); - if (peripheral > NUM_PERIPHERALS) - peripheral = -EINVAL; - } - - return peripheral; -} - int diag_md_write(int id, unsigned char *buf, int len, int ctx) { int i; diff --git a/drivers/char/diag/diag_mux.c b/drivers/char/diag/diag_mux.c index d6f6ea7af8ea..8cc803eef552 100644 --- a/drivers/char/diag/diag_mux.c +++ b/drivers/char/diag/diag_mux.c @@ -153,12 +153,15 @@ int diag_mux_write(int proc, unsigned char *buf, int len, int ctx) upd = PERIPHERAL_CDSP; break; case UPD_WLAN: - if (!driver->num_pd_session) + if (!driver->pd_logging_mode[0]) upd = PERIPHERAL_MODEM; break; case UPD_AUDIO: + if (!driver->pd_logging_mode[1]) + upd = PERIPHERAL_LPASS; + break; case UPD_SENSORS: - if (!driver->num_pd_session) + if (!driver->pd_logging_mode[2]) upd = PERIPHERAL_LPASS; break; default: diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index 5ae3e4defd0d..afaedc99a4e7 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -456,6 +456,7 @@ static void diag_close_logging_process(const int pid) { int i, j; int session_mask; + uint32_t p_mask; struct diag_md_session_t *session_info = NULL; struct diag_logging_mode_param_t params; @@ -475,6 +476,9 @@ static void diag_close_logging_process(const int pid) session_mask = session_info->peripheral_mask; diag_md_session_close(session_info); + p_mask = + diag_translate_kernel_to_user_mask(session_mask); + for (i = 0; i < NUM_MD_SESSIONS; i++) if (MD_PERIPHERAL_MASK(i) & session_mask) diag_mux_close_peripheral(DIAG_LOCAL_PROC, i); @@ -482,19 +486,17 @@ static void diag_close_logging_process(const int pid) params.req_mode = USB_MODE; params.mode_param = 0; params.pd_mask = 0; - params.peripheral_mask = - diag_translate_kernel_to_user_mask(session_mask); + params.peripheral_mask = p_mask; if (driver->num_pd_session > 0) { - for (i = UPD_WLAN; ((i < NUM_MD_SESSIONS) && - (session_mask & MD_PERIPHERAL_MASK(i))); - i++) { - j = i - UPD_WLAN; - driver->pd_session_clear[j] = 1; - driver->pd_logging_mode[j] = 0; - driver->num_pd_session -= 1; - params.pd_mask = - diag_translate_kernel_to_user_mask(session_mask); + for (i = UPD_WLAN; (i < NUM_MD_SESSIONS); i++) { + if (session_mask & MD_PERIPHERAL_MASK(i)) { + j = i - UPD_WLAN; + driver->pd_session_clear[j] = 1; + driver->pd_logging_mode[j] = 0; + driver->num_pd_session -= 1; + params.pd_mask = p_mask; + } } } diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c index e209039bed5a..9ac1ad62ffe0 100644 --- a/drivers/char/diag/diagfwd_peripheral.c +++ b/drivers/char/diag/diagfwd_peripheral.c @@ -216,6 +216,45 @@ static int check_bufsize_for_encoding(struct diagfwd_buf_t *buf, uint32_t len) return buf->len; } +int diag_md_get_peripheral(int ctxt) +{ + int peripheral; + + if (driver->num_pd_session) { + peripheral = GET_PD_CTXT(ctxt); + switch (peripheral) { + case UPD_WLAN: + if (!driver->pd_logging_mode[0]) + peripheral = PERIPHERAL_MODEM; + break; + case UPD_AUDIO: + if (!driver->pd_logging_mode[1]) + peripheral = PERIPHERAL_LPASS; + break; + case UPD_SENSORS: + if (!driver->pd_logging_mode[2]) + peripheral = PERIPHERAL_LPASS; + break; + case DIAG_ID_MPSS: + case DIAG_ID_LPASS: + case DIAG_ID_CDSP: + default: + peripheral = + GET_BUF_PERIPHERAL(ctxt); + if (peripheral > NUM_PERIPHERALS) + peripheral = -EINVAL; + break; + } + } else { + /* Account for Apps data as well */ + peripheral = GET_BUF_PERIPHERAL(ctxt); + if (peripheral > NUM_PERIPHERALS) + peripheral = -EINVAL; + } + + return peripheral; +} + static void diagfwd_data_process_done(struct diagfwd_info *fwd_info, struct diagfwd_buf_t *buf, int len) { @@ -245,13 +284,15 @@ static void diagfwd_data_process_done(struct diagfwd_info *fwd_info, mutex_lock(&driver->hdlc_disable_mutex); mutex_lock(&fwd_info->data_mutex); - peripheral = GET_PD_CTXT(buf->ctxt); - if (peripheral == DIAG_ID_MPSS) - peripheral = PERIPHERAL_MODEM; - if (peripheral == DIAG_ID_LPASS) - peripheral = PERIPHERAL_LPASS; - if (peripheral == DIAG_ID_CDSP) - peripheral = PERIPHERAL_CDSP; + peripheral = diag_md_get_peripheral(buf->ctxt); + if (peripheral < 0) { + pr_err("diag:%s:%d invalid peripheral = %d\n", + __func__, __LINE__, peripheral); + mutex_unlock(&fwd_info->data_mutex); + mutex_unlock(&driver->hdlc_disable_mutex); + diag_ws_release(); + return; + } session_info = diag_md_session_get_peripheral(peripheral); diff --git a/drivers/char/diag/diagfwd_peripheral.h b/drivers/char/diag/diagfwd_peripheral.h index 037eeebdeb35..eda70dcfdcd9 100644 --- a/drivers/char/diag/diagfwd_peripheral.h +++ b/drivers/char/diag/diagfwd_peripheral.h @@ -105,6 +105,9 @@ void diagfwd_early_open(uint8_t peripheral); void diagfwd_late_open(struct diagfwd_info *fwd_info); void diagfwd_close(uint8_t peripheral, uint8_t type); + +int diag_md_get_peripheral(int ctxt); + int diagfwd_register(uint8_t transport, uint8_t peripheral, uint8_t type, void *ctxt, struct diag_peripheral_ops *ops, struct diagfwd_info **fwd_ctxt); diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index 316d8b783d94..691c7bb3afac 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, 2016-2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2012, 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 @@ -764,6 +764,16 @@ static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode) pm_runtime_get_sync(drvdata->dev); mutex_lock(&drvdata->mem_lock); + + spin_lock_irqsave(&drvdata->spinlock, flags); + if (drvdata->reading) { + spin_unlock_irqrestore(&drvdata->spinlock, flags); + mutex_unlock(&drvdata->mem_lock); + pm_runtime_put(drvdata->dev); + return -EBUSY; + } + spin_unlock_irqrestore(&drvdata->spinlock, flags); + if (drvdata->config_type == TMC_CONFIG_TYPE_ETR && drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) { /* @@ -807,19 +817,8 @@ static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode) coresight_cti_map_trigout(drvdata->cti_flush, 1, 0); coresight_cti_map_trigin(drvdata->cti_reset, 2, 0); } - mutex_unlock(&drvdata->mem_lock); spin_lock_irqsave(&drvdata->spinlock, flags); - if (drvdata->reading) { - spin_unlock_irqrestore(&drvdata->spinlock, flags); - - if (drvdata->config_type == TMC_CONFIG_TYPE_ETR - && drvdata->out_mode == TMC_ETR_OUT_MODE_USB) - usb_qdss_close(drvdata->usbch); - pm_runtime_put(drvdata->dev); - - return -EBUSY; - } if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) { tmc_etb_enable_hw(drvdata); @@ -845,6 +844,7 @@ static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode) */ drvdata->sticky_enable = true; spin_unlock_irqrestore(&drvdata->spinlock, flags); + mutex_unlock(&drvdata->mem_lock); dev_info(drvdata->dev, "TMC enabled\n"); return 0; @@ -1140,6 +1140,7 @@ static int tmc_read_prepare(struct tmc_drvdata *drvdata) unsigned long flags; enum tmc_mode mode; + mutex_lock(&drvdata->mem_lock); spin_lock_irqsave(&drvdata->spinlock, flags); if (!drvdata->sticky_enable) { dev_err(drvdata->dev, "enable tmc once before reading\n"); @@ -1172,11 +1173,13 @@ static int tmc_read_prepare(struct tmc_drvdata *drvdata) out: drvdata->reading = true; spin_unlock_irqrestore(&drvdata->spinlock, flags); + mutex_unlock(&drvdata->mem_lock); dev_info(drvdata->dev, "TMC read start\n"); return 0; err: spin_unlock_irqrestore(&drvdata->spinlock, flags); + mutex_unlock(&drvdata->mem_lock); return ret; } @@ -1353,7 +1356,11 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len, { struct tmc_drvdata *drvdata = container_of(file->private_data, struct tmc_drvdata, miscdev); - char *bufp = drvdata->buf + *ppos; + char *bufp; + + mutex_lock(&drvdata->mem_lock); + + bufp = drvdata->buf + *ppos; if (*ppos + len > drvdata->size) len = drvdata->size - *ppos; @@ -1375,6 +1382,7 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len, if (copy_to_user(data, bufp, len)) { dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__); + mutex_unlock(&drvdata->mem_lock); return -EFAULT; } @@ -1382,6 +1390,8 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len, dev_dbg(drvdata->dev, "%s: %zu bytes copied, %d bytes left\n", __func__, len, (int)(drvdata->size - *ppos)); + + mutex_unlock(&drvdata->mem_lock); return len; } diff --git a/drivers/media/platform/msm/ais/sensor/flash/msm_flash.c b/drivers/media/platform/msm/ais/sensor/flash/msm_flash.c index 6af589e5c230..a2a89b92c9f1 100644 --- a/drivers/media/platform/msm/ais/sensor/flash/msm_flash.c +++ b/drivers/media/platform/msm/ais/sensor/flash/msm_flash.c @@ -1022,13 +1022,13 @@ static long msm_flash_subdev_do_ioctl( sd = vdev_to_v4l2_subdev(vdev); u32 = (struct msm_flash_cfg_data_t32 *)arg; - flash_data.cfg_type = u32->cfg_type; - for (i = 0; i < MAX_LED_TRIGGERS; i++) { - flash_data.flash_current[i] = u32->flash_current[i]; - flash_data.flash_duration[i] = u32->flash_duration[i]; - } switch (cmd) { case VIDIOC_MSM_FLASH_CFG32: + flash_data.cfg_type = u32->cfg_type; + for (i = 0; i < MAX_LED_TRIGGERS; i++) { + flash_data.flash_current[i] = u32->flash_current[i]; + flash_data.flash_duration[i] = u32->flash_duration[i]; + } cmd = VIDIOC_MSM_FLASH_CFG; switch (flash_data.cfg_type) { case CFG_FLASH_OFF: diff --git a/drivers/media/platform/msm/ais/sensor/ois/msm_ois.c b/drivers/media/platform/msm/ais/sensor/ois/msm_ois.c index 28a5402a4359..236660dca3fb 100644 --- a/drivers/media/platform/msm/ais/sensor/ois/msm_ois.c +++ b/drivers/media/platform/msm/ais/sensor/ois/msm_ois.c @@ -781,11 +781,10 @@ static long msm_ois_subdev_do_ioctl( u32 = (struct msm_ois_cfg_data32 *)arg; parg = arg; - ois_data.cfgtype = u32->cfgtype; - switch (cmd) { case VIDIOC_MSM_OIS_CFG32: cmd = VIDIOC_MSM_OIS_CFG; + ois_data.cfgtype = u32->cfgtype; switch (u32->cfgtype) { case CFG_OIS_CONTROL: diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c index acb697946e18..10f72a2155db 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c @@ -814,6 +814,9 @@ static void sde_hw_rotator_setup_wbengine(struct sde_hw_rotator_context *ctx, bw /= TRAFFIC_SHAPE_CLKTICK_12MS; if (bw > 0xFF) bw = 0xFF; + else if (bw == 0) + bw = 1; + SDE_REGDMA_WRITE(wrptr, ROT_WB_TRAFFIC_SHAPER_WR_CLIENT, BIT(31) | bw); SDEROT_DBG("Enable ROT_WB Traffic Shaper:%d\n", bw); diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig index 66bdc593f811..333d28e64087 100644 --- a/drivers/platform/msm/Kconfig +++ b/drivers/platform/msm/Kconfig @@ -194,7 +194,7 @@ config MSM_11AD tristate "Platform driver for 11ad chip" depends on PCI depends on PCI_MSM - default y + default m ---help--- This module adds required platform support for wireless adapter based on Qualcomm Technologies, Inc. 11ad chip, integrated into MSM platform diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c index 80514f6c738e..b7f451b7c6fd 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c @@ -1027,7 +1027,7 @@ static int __ipa_add_flt_rule(struct ipa_flt_tbl *tbl, enum ipa_ip_type ip, goto error; } - if (rt_tbl->cookie != IPA_COOKIE) { + if (rt_tbl->cookie != IPA_RT_TBL_COOKIE) { IPAERR("RT table cookie is invalid\n"); goto error; } @@ -1048,7 +1048,7 @@ static int __ipa_add_flt_rule(struct ipa_flt_tbl *tbl, enum ipa_ip_type ip, } INIT_LIST_HEAD(&entry->link); entry->rule = *rule; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_FLT_COOKIE; entry->rt_tbl = rt_tbl; entry->tbl = tbl; if (add_rear) { @@ -1067,13 +1067,19 @@ static int __ipa_add_flt_rule(struct ipa_flt_tbl *tbl, enum ipa_ip_type ip, if (id < 0) { IPAERR("failed to add to tree\n"); WARN_ON(1); + goto ipa_insert_failed; } *rule_hdl = id; entry->id = id; IPADBG_LOW("add flt rule rule_cnt=%d\n", tbl->rule_cnt); return 0; - +ipa_insert_failed: + tbl->rule_cnt--; + if (entry->rt_tbl) + entry->rt_tbl->ref_cnt--; + list_del(&entry->link); + kmem_cache_free(ipa_ctx->flt_rule_cache, entry); error: return -EPERM; } @@ -1089,7 +1095,7 @@ static int __ipa_del_flt_rule(u32 rule_hdl) return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_FLT_COOKIE) { IPAERR("bad params\n"); return -EINVAL; } @@ -1121,7 +1127,7 @@ static int __ipa_mdfy_flt_rule(struct ipa_flt_rule_mdfy *frule, goto error; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_FLT_COOKIE) { IPAERR("bad params\n"); goto error; } @@ -1142,7 +1148,7 @@ static int __ipa_mdfy_flt_rule(struct ipa_flt_rule_mdfy *frule, goto error; } - if (rt_tbl->cookie != IPA_COOKIE) { + if (rt_tbl->cookie != IPA_RT_TBL_COOKIE) { IPAERR("RT table cookie is invalid\n"); goto error; } diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c index 10a49b1e75d8..75e4ff5c3c57 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c @@ -547,7 +547,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, { struct ipa_hdr_entry *hdr_entry; struct ipa_hdr_proc_ctx_entry *entry; - struct ipa_hdr_proc_ctx_offset_entry *offset; + struct ipa_hdr_proc_ctx_offset_entry *offset = NULL; u32 bin; struct ipa_hdr_proc_ctx_tbl *htbl = &ipa_ctx->hdr_proc_ctx_tbl; int id; @@ -563,7 +563,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, } hdr_entry = ipa_id_find(proc_ctx->hdr_hdl); - if (!hdr_entry || (hdr_entry->cookie != IPA_COOKIE)) { + if (!hdr_entry || (hdr_entry->cookie != IPA_HDR_COOKIE)) { IPAERR("hdr_hdl is invalid\n"); return -EINVAL; } @@ -580,7 +580,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, entry->hdr = hdr_entry; if (add_ref_hdr) hdr_entry->ref_cnt++; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_PROC_HDR_COOKIE; needed_len = (proc_ctx->type == IPA_HDR_PROC_NONE) ? sizeof(struct ipa_hdr_proc_ctx_add_hdr_seq) : @@ -640,6 +640,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, if (id < 0) { IPAERR("failed to alloc id\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; proc_ctx->proc_ctx_hdl = id; @@ -647,6 +648,14 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, return 0; +ipa_insert_failed: + if (offset) + list_move(&offset->link, + &htbl->head_free_offset_list[offset->bin]); + entry->offset_entry = NULL; + list_del(&entry->link); + htbl->proc_ctx_cnt--; + bad_len: if (add_ref_hdr) hdr_entry->ref_cnt--; @@ -659,7 +668,7 @@ bad_len: static int __ipa_add_hdr(struct ipa_hdr_add *hdr) { struct ipa_hdr_entry *entry; - struct ipa_hdr_offset_entry *offset; + struct ipa_hdr_offset_entry *offset = NULL; u32 bin; struct ipa_hdr_tbl *htbl = &ipa_ctx->hdr_tbl; int id; @@ -691,7 +700,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) entry->type = hdr->type; entry->is_eth2_ofst_valid = hdr->is_eth2_ofst_valid; entry->eth2_ofst = hdr->eth2_ofst; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_HDR_COOKIE; if (hdr->hdr_len <= ipa_hdr_bin_sz[IPA_HDR_BIN0]) bin = IPA_HDR_BIN0; @@ -780,6 +789,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) if (id < 0) { IPAERR("failed to alloc id\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; hdr->hdr_hdl = id; @@ -804,10 +814,19 @@ fail_add_proc_ctx: entry->ref_cnt--; hdr->hdr_hdl = 0; ipa_id_remove(id); +ipa_insert_failed: + if (entry->is_hdr_proc_ctx) { + dma_unmap_single(ipa_ctx->pdev, entry->phys_base, + entry->hdr_len, DMA_TO_DEVICE); + } else { + if (offset) + list_move(&offset->link, + &htbl->head_free_offset_list[offset->bin]); + entry->offset_entry = NULL; + } htbl->hdr_cnt--; list_del(&entry->link); - dma_unmap_single(ipa_ctx->pdev, entry->phys_base, - entry->hdr_len, DMA_TO_DEVICE); + fail_dma_mapping: entry->is_hdr_proc_ctx = false; bad_hdr_len: @@ -824,7 +843,7 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, struct ipa_hdr_proc_ctx_tbl *htbl = &ipa_ctx->hdr_proc_ctx_tbl; entry = ipa_id_find(proc_ctx_hdl); - if (!entry || (entry->cookie != IPA_COOKIE)) { + if (!entry || (entry->cookie != IPA_PROC_HDR_COOKIE)) { IPAERR("bad parm\n"); return -EINVAL; } @@ -875,7 +894,7 @@ int __ipa_del_hdr(u32 hdr_hdl, bool by_user) return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_HDR_COOKIE) { IPAERR("bad parm\n"); return -EINVAL; } @@ -1444,7 +1463,7 @@ int ipa2_put_hdr(u32 hdr_hdl) goto bail; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_HDR_COOKIE) { IPAERR("invalid header entry\n"); result = -EINVAL; goto bail; diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h index bb11230c960a..70b2a2eeb53f 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h @@ -37,7 +37,15 @@ #define DRV_NAME "ipa" #define NAT_DEV_NAME "ipaNatTable" + #define IPA_COOKIE 0x57831603 +#define IPA_RT_RULE_COOKIE 0x57831604 +#define IPA_RT_TBL_COOKIE 0x57831605 +#define IPA_FLT_COOKIE 0x57831606 +#define IPA_HDR_COOKIE 0x57831607 +#define IPA_PROC_HDR_COOKIE 0x57831608 + + #define MTU_BYTE 1500 #define IPA_MAX_NUM_PIPES 0x14 @@ -223,8 +231,8 @@ struct ipa_smmu_cb_ctx { */ struct ipa_flt_entry { struct list_head link; - struct ipa_flt_rule rule; u32 cookie; + struct ipa_flt_rule rule; struct ipa_flt_tbl *tbl; struct ipa_rt_tbl *rt_tbl; u32 hw_len; @@ -249,13 +257,13 @@ struct ipa_flt_entry { */ struct ipa_rt_tbl { struct list_head link; + u32 cookie; struct list_head head_rt_rule_list; char name[IPA_RESOURCE_NAME_MAX]; u32 idx; u32 rule_cnt; u32 ref_cnt; struct ipa_rt_tbl_set *set; - u32 cookie; bool in_sys; u32 sz; struct ipa_mem_buffer curr_mem; @@ -286,6 +294,7 @@ struct ipa_rt_tbl { */ struct ipa_hdr_entry { struct list_head link; + u32 cookie; u8 hdr[IPA_HDR_MAX_SIZE]; u32 hdr_len; char name[IPA_RESOURCE_NAME_MAX]; @@ -295,7 +304,6 @@ struct ipa_hdr_entry { dma_addr_t phys_base; struct ipa_hdr_proc_ctx_entry *proc_ctx; struct ipa_hdr_offset_entry *offset_entry; - u32 cookie; u32 ref_cnt; int id; u8 is_eth2_ofst_valid; @@ -368,10 +376,10 @@ struct ipa_hdr_proc_ctx_add_hdr_cmd_seq { */ struct ipa_hdr_proc_ctx_entry { struct list_head link; + u32 cookie; enum ipa_hdr_proc_type type; struct ipa_hdr_proc_ctx_offset_entry *offset_entry; struct ipa_hdr_entry *hdr; - u32 cookie; u32 ref_cnt; int id; bool user_deleted; @@ -427,8 +435,8 @@ struct ipa_flt_tbl { */ struct ipa_rt_entry { struct list_head link; - struct ipa_rt_rule rule; u32 cookie; + struct ipa_rt_rule rule; struct ipa_rt_tbl *tbl; struct ipa_hdr_entry *hdr; struct ipa_hdr_proc_ctx_entry *proc_ctx; diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c index f2909110d09f..9ac7b3809895 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c @@ -909,7 +909,7 @@ static struct ipa_rt_tbl *__ipa_add_rt_tbl(enum ipa_ip_type ip, INIT_LIST_HEAD(&entry->link); strlcpy(entry->name, name, IPA_RESOURCE_NAME_MAX); entry->set = set; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_RT_TBL_COOKIE; entry->in_sys = (ip == IPA_IP_v4) ? !ipa_ctx->ip4_rt_tbl_lcl : !ipa_ctx->ip6_rt_tbl_lcl; set->tbl_cnt++; @@ -922,12 +922,16 @@ static struct ipa_rt_tbl *__ipa_add_rt_tbl(enum ipa_ip_type ip, if (id < 0) { IPAERR("failed to add to tree\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; } return entry; +ipa_insert_failed: + set->tbl_cnt--; + list_del(&entry->link); fail_rt_idx_alloc: entry->cookie = 0; kmem_cache_free(ipa_ctx->rt_tbl_cache, entry); @@ -940,7 +944,7 @@ static int __ipa_del_rt_tbl(struct ipa_rt_tbl *entry) enum ipa_ip_type ip = IPA_IP_MAX; u32 id; - if (entry == NULL || (entry->cookie != IPA_COOKIE)) { + if (entry == NULL || (entry->cookie != IPA_RT_TBL_COOKIE)) { IPAERR("bad parms\n"); return -EINVAL; } @@ -954,8 +958,11 @@ static int __ipa_del_rt_tbl(struct ipa_rt_tbl *entry) ip = IPA_IP_v4; else if (entry->set == &ipa_ctx->rt_tbl_set[IPA_IP_v6]) ip = IPA_IP_v6; - else + else { WARN_ON(1); + return -EPERM; + } + if (!entry->in_sys) { list_del(&entry->link); @@ -994,13 +1001,14 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, if (rule->hdr_hdl) { hdr = ipa_id_find(rule->hdr_hdl); - if ((hdr == NULL) || (hdr->cookie != IPA_COOKIE)) { + if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) { IPAERR("rt rule does not point to valid hdr\n"); goto error; } } else if (rule->hdr_proc_ctx_hdl) { proc_ctx = ipa_id_find(rule->hdr_proc_ctx_hdl); - if ((proc_ctx == NULL) || (proc_ctx->cookie != IPA_COOKIE)) { + if ((proc_ctx == NULL) || + (proc_ctx->cookie != IPA_PROC_HDR_COOKIE)) { IPAERR("rt rule does not point to valid proc ctx\n"); goto error; } @@ -1008,7 +1016,7 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, tbl = __ipa_add_rt_tbl(ip, name); - if (tbl == NULL || (tbl->cookie != IPA_COOKIE)) { + if (tbl == NULL || (tbl->cookie != IPA_RT_TBL_COOKIE)) { IPAERR("bad params\n"); goto error; } @@ -1029,7 +1037,7 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, goto error; } INIT_LIST_HEAD(&entry->link); - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_RT_RULE_COOKIE; entry->rule = *rule; entry->tbl = tbl; entry->hdr = hdr; @@ -1123,7 +1131,7 @@ int __ipa_del_rt_rule(u32 rule_hdl) return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_RT_RULE_COOKIE) { IPAERR("bad params\n"); return -EINVAL; } @@ -1358,7 +1366,7 @@ int ipa2_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup) } mutex_lock(&ipa_ctx->lock); entry = __ipa_find_rt_tbl(lookup->ip, lookup->name); - if (entry && entry->cookie == IPA_COOKIE) { + if (entry && entry->cookie == IPA_RT_TBL_COOKIE) { if (entry->ref_cnt == U32_MAX) { IPAERR("fail: ref count crossed limit\n"); goto ret; @@ -1401,7 +1409,7 @@ int ipa2_put_rt_tbl(u32 rt_tbl_hdl) goto ret; } - if ((entry->cookie != IPA_COOKIE) || entry->ref_cnt == 0) { + if ((entry->cookie != IPA_RT_TBL_COOKIE) || entry->ref_cnt == 0) { IPAERR("bad parms\n"); result = -EINVAL; goto ret; @@ -1411,8 +1419,11 @@ int ipa2_put_rt_tbl(u32 rt_tbl_hdl) ip = IPA_IP_v4; else if (entry->set == &ipa_ctx->rt_tbl_set[IPA_IP_v6]) ip = IPA_IP_v6; - else + else { WARN_ON(1); + result = -EINVAL; + goto ret; + } entry->ref_cnt--; if (entry->ref_cnt == 0 && entry->rule_cnt == 0) { @@ -1439,7 +1450,7 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) if (rtrule->rule.hdr_hdl) { hdr = ipa_id_find(rtrule->rule.hdr_hdl); - if ((hdr == NULL) || (hdr->cookie != IPA_COOKIE)) { + if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) { IPAERR("rt rule does not point to valid hdr\n"); goto error; } @@ -1451,7 +1462,7 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) goto error; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_RT_RULE_COOKIE) { IPAERR("bad params\n"); goto error; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c index 41b29335d23b..42632c527bdd 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c @@ -745,7 +745,7 @@ static int __ipa_validate_flt_rule(const struct ipa_flt_rule *rule, goto error; } - if ((*rt_tbl)->cookie != IPA_COOKIE) { + if ((*rt_tbl)->cookie != IPA_RT_TBL_COOKIE) { IPAERR("RT table cookie is invalid\n"); goto error; } @@ -787,7 +787,7 @@ static int __ipa_create_flt_entry(struct ipa3_flt_entry **entry, } INIT_LIST_HEAD(&((*entry)->link)); (*entry)->rule = *rule; - (*entry)->cookie = IPA_COOKIE; + (*entry)->cookie = IPA_FLT_COOKIE; (*entry)->rt_tbl = rt_tbl; (*entry)->tbl = tbl; if (rule->rule_id) { @@ -822,12 +822,18 @@ static int __ipa_finish_flt_rule_add(struct ipa3_flt_tbl *tbl, if (id < 0) { IPAERR("failed to add to tree\n"); WARN_ON(1); + goto ipa_insert_failed; } *rule_hdl = id; entry->id = id; IPADBG_LOW("add flt rule rule_cnt=%d\n", tbl->rule_cnt); return 0; +ipa_insert_failed: + if (entry->rt_tbl) + entry->rt_tbl->ref_cnt--; + tbl->rule_cnt--; + return -EPERM; } static int __ipa_add_flt_rule(struct ipa3_flt_tbl *tbl, enum ipa_ip_type ip, @@ -853,9 +859,16 @@ static int __ipa_add_flt_rule(struct ipa3_flt_tbl *tbl, enum ipa_ip_type ip, list_add(&entry->link, &tbl->head_flt_rule_list); } - __ipa_finish_flt_rule_add(tbl, entry, rule_hdl); + if (__ipa_finish_flt_rule_add(tbl, entry, rule_hdl)) + goto ipa_insert_failed; return 0; +ipa_insert_failed: + list_del(&entry->link); + /* if rule id was allocated from idr, remove it */ + if (!(entry->rule_id & ipahal_get_rule_id_hi_bit())) + idr_remove(&entry->tbl->rule_ids, entry->rule_id); + kmem_cache_free(ipa3_ctx->flt_rule_cache, entry); error: return -EPERM; @@ -887,7 +900,8 @@ static int __ipa_add_flt_rule_after(struct ipa3_flt_tbl *tbl, list_add(&entry->link, &((*add_after_entry)->link)); - __ipa_finish_flt_rule_add(tbl, entry, rule_hdl); + if (__ipa_finish_flt_rule_add(tbl, entry, rule_hdl)) + goto ipa_insert_failed; /* * prepare for next insertion @@ -896,6 +910,13 @@ static int __ipa_add_flt_rule_after(struct ipa3_flt_tbl *tbl, return 0; +ipa_insert_failed: + list_del(&entry->link); + /* if rule id was allocated from idr, remove it */ + if (!(entry->rule_id & ipahal_get_rule_id_hi_bit())) + idr_remove(&entry->tbl->rule_ids, entry->rule_id); + kmem_cache_free(ipa3_ctx->flt_rule_cache, entry); + error: *add_after_entry = NULL; return -EPERM; @@ -912,7 +933,7 @@ static int __ipa_del_flt_rule(u32 rule_hdl) return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_FLT_COOKIE) { IPAERR("bad params\n"); return -EINVAL; } @@ -949,7 +970,7 @@ static int __ipa_mdfy_flt_rule(struct ipa_flt_rule_mdfy *frule, goto error; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_FLT_COOKIE) { IPAERR("bad params\n"); goto error; } @@ -970,7 +991,7 @@ static int __ipa_mdfy_flt_rule(struct ipa_flt_rule_mdfy *frule, goto error; } - if (rt_tbl->cookie != IPA_COOKIE) { + if (rt_tbl->cookie != IPA_RT_TBL_COOKIE) { IPAERR("RT table cookie is invalid\n"); goto error; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c index a5186f1aff35..34bc7dcd63cf 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c @@ -339,7 +339,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, IPAERR("hdr_hdl is invalid\n"); return -EINVAL; } - if (hdr_entry->cookie != IPA_COOKIE) { + if (hdr_entry->cookie != IPA_HDR_COOKIE) { IPAERR("Invalid header cookie %u\n", hdr_entry->cookie); WARN_ON(1); return -EINVAL; @@ -359,7 +359,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, entry->hdr = hdr_entry; if (add_ref_hdr) hdr_entry->ref_cnt++; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_HDR_COOKIE; needed_len = ipahal_get_proc_ctx_needed_len(proc_ctx->type); @@ -417,6 +417,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, if (id < 0) { IPAERR("failed to alloc id\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; proc_ctx->proc_ctx_hdl = id; @@ -424,6 +425,14 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, return 0; +ipa_insert_failed: + if (offset) + list_move(&offset->link, + &htbl->head_free_offset_list[offset->bin]); + entry->offset_entry = NULL; + list_del(&entry->link); + htbl->proc_ctx_cnt--; + bad_len: if (add_ref_hdr) hdr_entry->ref_cnt--; @@ -436,7 +445,7 @@ bad_len: static int __ipa_add_hdr(struct ipa_hdr_add *hdr) { struct ipa3_hdr_entry *entry; - struct ipa_hdr_offset_entry *offset; + struct ipa_hdr_offset_entry *offset = NULL; u32 bin; struct ipa3_hdr_tbl *htbl = &ipa3_ctx->hdr_tbl; int id; @@ -467,7 +476,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) entry->type = hdr->type; entry->is_eth2_ofst_valid = hdr->is_eth2_ofst_valid; entry->eth2_ofst = hdr->eth2_ofst; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_HDR_COOKIE; if (hdr->hdr_len <= ipa_hdr_bin_sz[IPA_HDR_BIN0]) bin = IPA_HDR_BIN0; @@ -546,6 +555,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) if (id < 0) { IPAERR("failed to alloc id\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; hdr->hdr_hdl = id; @@ -570,10 +580,19 @@ fail_add_proc_ctx: entry->ref_cnt--; hdr->hdr_hdl = 0; ipa3_id_remove(id); +ipa_insert_failed: + if (entry->is_hdr_proc_ctx) { + dma_unmap_single(ipa3_ctx->pdev, entry->phys_base, + entry->hdr_len, DMA_TO_DEVICE); + } else { + if (offset) + list_move(&offset->link, + &htbl->head_free_offset_list[offset->bin]); + entry->offset_entry = NULL; + } htbl->hdr_cnt--; list_del(&entry->link); - dma_unmap_single(ipa3_ctx->pdev, entry->phys_base, - entry->hdr_len, DMA_TO_DEVICE); + fail_dma_mapping: entry->is_hdr_proc_ctx = false; @@ -591,7 +610,7 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, struct ipa3_hdr_proc_ctx_tbl *htbl = &ipa3_ctx->hdr_proc_ctx_tbl; entry = ipa3_id_find(proc_ctx_hdl); - if (!entry || (entry->cookie != IPA_COOKIE)) { + if (!entry || (entry->cookie != IPA_HDR_COOKIE)) { IPAERR("bad parm\n"); return -EINVAL; } @@ -642,7 +661,7 @@ int __ipa3_del_hdr(u32 hdr_hdl, bool by_user) return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_HDR_COOKIE) { IPAERR("bad parm\n"); return -EINVAL; } @@ -1188,7 +1207,7 @@ int ipa3_put_hdr(u32 hdr_hdl) goto bail; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_HDR_COOKIE) { IPAERR("invalid header entry\n"); result = -EINVAL; goto bail; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index ac7ef6a21952..cbc53fb6815d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -40,6 +40,12 @@ #define DRV_NAME "ipa" #define NAT_DEV_NAME "ipaNatTable" #define IPA_COOKIE 0x57831603 +#define IPA_RT_RULE_COOKIE 0x57831604 +#define IPA_RT_TBL_COOKIE 0x57831605 +#define IPA_FLT_COOKIE 0x57831606 +#define IPA_HDR_COOKIE 0x57831607 +#define IPA_PROC_HDR_COOKIE 0x57831608 + #define MTU_BYTE 1500 #define IPA_EP_NOT_ALLOCATED (-1) @@ -217,8 +223,8 @@ struct ipa_smmu_cb_ctx { */ struct ipa3_flt_entry { struct list_head link; - struct ipa_flt_rule rule; u32 cookie; + struct ipa_flt_rule rule; struct ipa3_flt_tbl *tbl; struct ipa3_rt_tbl *rt_tbl; u32 hw_len; @@ -246,13 +252,13 @@ struct ipa3_flt_entry { */ struct ipa3_rt_tbl { struct list_head link; + u32 cookie; struct list_head head_rt_rule_list; char name[IPA_RESOURCE_NAME_MAX]; u32 idx; u32 rule_cnt; u32 ref_cnt; struct ipa3_rt_tbl_set *set; - u32 cookie; bool in_sys[IPA_RULE_TYPE_MAX]; u32 sz[IPA_RULE_TYPE_MAX]; struct ipa_mem_buffer curr_mem[IPA_RULE_TYPE_MAX]; @@ -284,6 +290,7 @@ struct ipa3_rt_tbl { */ struct ipa3_hdr_entry { struct list_head link; + u32 cookie; u8 hdr[IPA_HDR_MAX_SIZE]; u32 hdr_len; char name[IPA_RESOURCE_NAME_MAX]; @@ -293,7 +300,6 @@ struct ipa3_hdr_entry { dma_addr_t phys_base; struct ipa3_hdr_proc_ctx_entry *proc_ctx; struct ipa_hdr_offset_entry *offset_entry; - u32 cookie; u32 ref_cnt; int id; u8 is_eth2_ofst_valid; @@ -342,10 +348,10 @@ struct ipa3_hdr_proc_ctx_offset_entry { */ struct ipa3_hdr_proc_ctx_entry { struct list_head link; + u32 cookie; enum ipa_hdr_proc_type type; struct ipa3_hdr_proc_ctx_offset_entry *offset_entry; struct ipa3_hdr_entry *hdr; - u32 cookie; u32 ref_cnt; int id; bool user_deleted; @@ -407,8 +413,8 @@ struct ipa3_flt_tbl { */ struct ipa3_rt_entry { struct list_head link; - struct ipa_rt_rule rule; u32 cookie; + struct ipa_rt_rule rule; struct ipa3_rt_tbl *tbl; struct ipa3_hdr_entry *hdr; struct ipa3_hdr_proc_ctx_entry *proc_ctx; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c index 6197c9f64ca5..2ade584890fb 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c @@ -796,7 +796,7 @@ static struct ipa3_rt_tbl *__ipa_add_rt_tbl(enum ipa_ip_type ip, INIT_LIST_HEAD(&entry->link); strlcpy(entry->name, name, IPA_RESOURCE_NAME_MAX); entry->set = set; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_RT_TBL_COOKIE; entry->in_sys[IPA_RULE_HASHABLE] = (ip == IPA_IP_v4) ? !ipa3_ctx->ip4_rt_tbl_hash_lcl : !ipa3_ctx->ip6_rt_tbl_hash_lcl; @@ -814,12 +814,16 @@ static struct ipa3_rt_tbl *__ipa_add_rt_tbl(enum ipa_ip_type ip, if (id < 0) { IPAERR("failed to add to tree\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; } return entry; - +ipa_insert_failed: + set->tbl_cnt--; + list_del(&entry->link); + idr_destroy(&entry->rule_ids); fail_rt_idx_alloc: entry->cookie = 0; kmem_cache_free(ipa3_ctx->rt_tbl_cache, entry); @@ -833,7 +837,7 @@ static int __ipa_del_rt_tbl(struct ipa3_rt_tbl *entry) u32 id; struct ipa3_rt_tbl_set *rset; - if (entry == NULL || (entry->cookie != IPA_COOKIE)) { + if (entry == NULL || (entry->cookie != IPA_RT_TBL_COOKIE)) { IPAERR("bad parms\n"); return -EINVAL; } @@ -847,8 +851,10 @@ static int __ipa_del_rt_tbl(struct ipa3_rt_tbl *entry) ip = IPA_IP_v4; else if (entry->set == &ipa3_ctx->rt_tbl_set[IPA_IP_v6]) ip = IPA_IP_v6; - else + else { WARN_ON(1); + return -EPERM; + } rset = &ipa3_ctx->reap_rt_tbl_set[ip]; @@ -885,14 +891,14 @@ static int __ipa_rt_validate_hndls(const struct ipa_rt_rule *rule, if (rule->hdr_hdl) { *hdr = ipa3_id_find(rule->hdr_hdl); - if ((*hdr == NULL) || ((*hdr)->cookie != IPA_COOKIE)) { + if ((*hdr == NULL) || ((*hdr)->cookie != IPA_HDR_COOKIE)) { IPAERR("rt rule does not point to valid hdr\n"); return -EPERM; } } else if (rule->hdr_proc_ctx_hdl) { *proc_ctx = ipa3_id_find(rule->hdr_proc_ctx_hdl); if ((*proc_ctx == NULL) || - ((*proc_ctx)->cookie != IPA_COOKIE)) { + ((*proc_ctx)->cookie != IPA_PROC_HDR_COOKIE)) { IPAERR("rt rule does not point to valid proc ctx\n"); return -EPERM; @@ -915,7 +921,7 @@ static int __ipa_create_rt_entry(struct ipa3_rt_entry **entry, goto error; } INIT_LIST_HEAD(&(*entry)->link); - (*(entry))->cookie = IPA_COOKIE; + (*(entry))->cookie = IPA_RT_RULE_COOKIE; (*(entry))->rule = *rule; (*(entry))->tbl = tbl; (*(entry))->hdr = hdr; @@ -983,7 +989,7 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, tbl = __ipa_add_rt_tbl(ip, name); - if (tbl == NULL || (tbl->cookie != IPA_COOKIE)) { + if (tbl == NULL || (tbl->cookie != IPA_RT_TBL_COOKIE)) { IPAERR("failed adding rt tbl name = %s\n", name ? name : ""); goto error; @@ -1118,7 +1124,7 @@ int ipa3_add_rt_rule_after(struct ipa_ioc_add_rt_rule_after *rules) mutex_lock(&ipa3_ctx->lock); tbl = __ipa3_find_rt_tbl(rules->ip, rules->rt_tbl_name); - if (tbl == NULL || (tbl->cookie != IPA_COOKIE)) { + if (tbl == NULL || (tbl->cookie != IPA_RT_TBL_COOKIE)) { IPAERR("failed finding rt tbl name = %s\n", rules->rt_tbl_name ? rules->rt_tbl_name : ""); ret = -EINVAL; @@ -1202,7 +1208,7 @@ int __ipa3_del_rt_rule(u32 rule_hdl) return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_RT_RULE_COOKIE) { IPAERR("bad params\n"); return -EINVAL; } @@ -1440,7 +1446,7 @@ int ipa3_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup) } mutex_lock(&ipa3_ctx->lock); entry = __ipa3_find_rt_tbl(lookup->ip, lookup->name); - if (entry && entry->cookie == IPA_COOKIE) { + if (entry && entry->cookie == IPA_RT_TBL_COOKIE) { if (entry->ref_cnt == U32_MAX) { IPAERR("fail: ref count crossed limit\n"); goto ret; @@ -1483,7 +1489,7 @@ int ipa3_put_rt_tbl(u32 rt_tbl_hdl) goto ret; } - if ((entry->cookie != IPA_COOKIE) || entry->ref_cnt == 0) { + if ((entry->cookie != IPA_RT_TBL_COOKIE) || entry->ref_cnt == 0) { IPAERR("bad parms\n"); result = -EINVAL; goto ret; @@ -1493,8 +1499,10 @@ int ipa3_put_rt_tbl(u32 rt_tbl_hdl) ip = IPA_IP_v4; else if (entry->set == &ipa3_ctx->rt_tbl_set[IPA_IP_v6]) ip = IPA_IP_v6; - else + else { WARN_ON(1); + goto ret; + } entry->ref_cnt--; if (entry->ref_cnt == 0 && entry->rule_cnt == 0) { @@ -1524,13 +1532,14 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) if (rtrule->rule.hdr_hdl) { hdr = ipa3_id_find(rtrule->rule.hdr_hdl); - if ((hdr == NULL) || (hdr->cookie != IPA_COOKIE)) { + if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) { IPAERR("rt rule does not point to valid hdr\n"); goto error; } } else if (rtrule->rule.hdr_proc_ctx_hdl) { proc_ctx = ipa3_id_find(rtrule->rule.hdr_proc_ctx_hdl); - if ((proc_ctx == NULL) || (proc_ctx->cookie != IPA_COOKIE)) { + if ((proc_ctx == NULL) || + (proc_ctx->cookie != IPA_PROC_HDR_COOKIE)) { IPAERR("rt rule does not point to valid proc ctx\n"); goto error; } @@ -1542,7 +1551,7 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) goto error; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_RT_RULE_COOKIE) { IPAERR("bad params\n"); goto error; } diff --git a/drivers/power/qcom/msm-core.c b/drivers/power/qcom/msm-core.c index 43ad33ea234b..825c27e7a4c1 100644 --- a/drivers/power/qcom/msm-core.c +++ b/drivers/power/qcom/msm-core.c @@ -190,10 +190,12 @@ static void core_temp_notify(enum thermal_trip_type type, struct cpu_activity_info *cpu_node = (struct cpu_activity_info *) data; + temp /= scaling_factor; + trace_temp_notification(cpu_node->sensor_id, type, temp, cpu_node->temp); - cpu_node->temp = temp / scaling_factor; + cpu_node->temp = temp; complete(&sampling_completion); } diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c index 0908eea3b186..7b7f991ecba9 100644 --- a/drivers/power/supply/qcom/qpnp-smb2.c +++ b/drivers/power/supply/qcom/qpnp-smb2.c @@ -1847,6 +1847,12 @@ static int smb2_post_init(struct smb2 *chip) struct smb_charger *chg = &chip->chg; int rc; + /* In case the usb path is suspended, we would have missed disabling + * the icl change interrupt because the interrupt could have been + * not requested + */ + rerun_election(chg->usb_icl_votable); + /* configure power role for dual-role */ rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, TYPEC_POWER_ROLE_CMD_MASK, 0); @@ -2196,6 +2202,8 @@ static int smb2_request_interrupts(struct smb2 *chip) return rc; } } + if (chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq) + chg->usb_icl_change_irq_enabled = true; return rc; } diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index 16db425514c3..64ed53185e88 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -427,6 +427,14 @@ static int step_charge_soc_update(struct smb_charger *chg, int capacity) int smblib_set_usb_suspend(struct smb_charger *chg, bool suspend) { int rc = 0; + int irq = chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq; + + if (suspend && irq) { + if (chg->usb_icl_change_irq_enabled) { + disable_irq_nosync(irq); + chg->usb_icl_change_irq_enabled = false; + } + } rc = smblib_masked_write(chg, USBIN_CMD_IL_REG, USBIN_SUSPEND_BIT, suspend ? USBIN_SUSPEND_BIT : 0); @@ -434,6 +442,13 @@ int smblib_set_usb_suspend(struct smb_charger *chg, bool suspend) smblib_err(chg, "Couldn't write %s to USBIN_SUSPEND_BIT rc=%d\n", suspend ? "suspend" : "resume", rc); + if (!suspend && irq) { + if (!chg->usb_icl_change_irq_enabled) { + enable_irq(irq); + chg->usb_icl_change_irq_enabled = true; + } + } + return rc; } @@ -885,7 +900,6 @@ int smblib_set_icl_current(struct smb_charger *chg, int icl_ua) if (icl_ua < USBIN_25MA) return smblib_set_usb_suspend(chg, true); - disable_irq_nosync(chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq); if (icl_ua == INT_MAX) goto override_suspend_config; @@ -943,7 +957,6 @@ override_suspend_config: } enable_icl_changed_interrupt: - enable_irq(chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq); return rc; } diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h index c97b84c34084..18714827b8d2 100644 --- a/drivers/power/supply/qcom/smb-lib.h +++ b/drivers/power/supply/qcom/smb-lib.h @@ -328,6 +328,7 @@ struct smb_charger { int fake_input_current_limited; bool pr_swap_in_progress; int typec_mode; + int usb_icl_change_irq_enabled; /* workaround flag */ u32 wa_flags; diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c index 830ef92ffe80..fc9faaee3170 100644 --- a/drivers/tty/serial/msm_serial_hs.c +++ b/drivers/tty/serial/msm_serial_hs.c @@ -272,7 +272,7 @@ static struct of_device_id msm_hs_match_table[] = { #define UARTDM_TX_BUF_SIZE UART_XMIT_SIZE #define UARTDM_RX_BUF_SIZE 512 #define RETRY_TIMEOUT 5 -#define UARTDM_NR 256 +#define UARTDM_NR 4 #define BAM_PIPE_MIN 0 #define BAM_PIPE_MAX 11 #define BUS_SCALING 1 diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index 03aeec2e878c..7cdc95d2b085 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -182,7 +182,7 @@ static void *usbpd_ipc_log; #define PS_HARD_RESET_TIME 25 #define PS_SOURCE_ON 400 #define PS_SOURCE_OFF 750 -#define SWAP_SOURCE_START_TIME 20 +#define FIRST_SOURCE_CAP_TIME 200 #define VDM_BUSY_TIME 50 #define VCONN_ON_TIME 100 @@ -790,17 +790,27 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) pd->pd_phy_opened = true; } - pd->current_state = PE_SRC_SEND_CAPABILITIES; if (pd->in_pr_swap) { - kick_sm(pd, SWAP_SOURCE_START_TIME); pd->in_pr_swap = false; val.intval = 0; power_supply_set_property(pd->usb_psy, POWER_SUPPLY_PROP_PR_SWAP, &val); - break; } - /* fall-through */ + /* + * A sink might remove its terminations (during some Type-C + * compliance tests or a sink attempting to do Try.SRC) + * at this point just after we enabled VBUS. Sending PD + * messages now would delay detecting the detach beyond the + * required timing. Instead, delay sending out the first + * source capabilities to allow for the other side to + * completely settle CC debounce and allow HW to detect detach + * sooner in the meantime. PD spec allows up to + * tFirstSourceCap (250ms). + */ + pd->current_state = PE_SRC_SEND_CAPABILITIES; + kick_sm(pd, FIRST_SOURCE_CAP_TIME); + break; case PE_SRC_SEND_CAPABILITIES: kick_sm(pd, 0); diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h index d6e8a213c215..5548f0f09f8a 100644 --- a/drivers/video/fbdev/msm/mdss.h +++ b/drivers/video/fbdev/msm/mdss.h @@ -547,6 +547,7 @@ struct mdss_data_type { u32 sec_session_cnt; wait_queue_head_t secure_waitq; struct cx_ipeak_client *mdss_cx_ipeak; + struct mult_factor bus_throughput_factor; }; extern struct mdss_data_type *mdss_res; diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index 6936c4c1f3cc..6fb32761a767 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -4527,6 +4527,15 @@ static int mdss_mdp_parse_dt_misc(struct platform_device *pdev) mdss_mdp_parse_dt_fudge_factors(pdev, "qcom,mdss-clk-factor", &mdata->clk_factor); + /* + * Bus throughput factor will be used during high downscale cases. + * The recommended default factor is 1.1. + */ + mdata->bus_throughput_factor.numer = 11; + mdata->bus_throughput_factor.denom = 10; + mdss_mdp_parse_dt_fudge_factors(pdev, "qcom,mdss-bus-througput-factor", + &mdata->bus_throughput_factor); + rc = of_property_read_u32(pdev->dev.of_node, "qcom,max-bandwidth-low-kbps", &mdata->max_bw_low); if (rc) diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index efd681a5d954..0165c48a0467 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -31,6 +31,7 @@ #define MDSS_MDP_QSEED3_VER_DOWNSCALE_LIM 2 #define NUM_MIXERCFG_REGS 3 #define MDSS_MDP_WB_OUTPUT_BPP 3 +#define MIN_BUS_THROUGHPUT_SCALE_FACTOR 35 struct mdss_mdp_mixer_cfg { u32 config_masks[NUM_MIXERCFG_REGS]; bool border_enabled; @@ -622,11 +623,21 @@ static u32 __calc_qseed3_mdp_clk_rate(struct mdss_mdp_pipe *pipe, } static inline bool __is_vert_downscaling(u32 src_h, - struct mdss_rect dst){ - + struct mdss_rect dst) +{ return (src_h > dst.h); } +static inline bool __is_bus_throughput_factor_required(u32 src_h, + struct mdss_rect dst) +{ + u32 scale_factor = src_h * 10; + + do_div(scale_factor, dst.h); + return (__is_vert_downscaling(src_h, dst) && + (scale_factor >= MIN_BUS_THROUGHPUT_SCALE_FACTOR)); +} + static u32 get_pipe_mdp_clk_rate(struct mdss_mdp_pipe *pipe, struct mdss_rect src, struct mdss_rect dst, u32 fps, u32 v_total, u32 flags) @@ -673,6 +684,15 @@ static u32 get_pipe_mdp_clk_rate(struct mdss_mdp_pipe *pipe, } } + /* + * If the downscale factor is >= 3.5 for a 32 BPP surface, + * it is recommended to add a 10% bus throughput factor to + * the clock rate. + */ + if ((pipe->src_fmt->bpp == 4) && + __is_bus_throughput_factor_required(src_h, dst)) + rate = apply_fudge_factor(rate, &mdata->bus_throughput_factor); + if (flags & PERF_CALC_PIPE_APPLY_CLK_FUDGE) rate = mdss_mdp_clk_fudge_factor(mixer, rate); diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c index e44edb8fbea7..3ccc09d58480 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_layer.c +++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c @@ -3131,6 +3131,14 @@ int mdss_mdp_layer_pre_commit_wfd(struct msm_fb_data_type *mfd, sync_pt_data = &mfd->mdp_sync_pt_data; mutex_lock(&sync_pt_data->sync_mutex); count = sync_pt_data->acq_fen_cnt; + + if (count >= MDP_MAX_FENCE_FD) { + pr_err("Reached maximum possible value for fence count\n"); + mutex_unlock(&sync_pt_data->sync_mutex); + rc = -EINVAL; + goto input_layer_err; + } + sync_pt_data->acq_fen[count] = fence; sync_pt_data->acq_fen_cnt++; mutex_unlock(&sync_pt_data->sync_mutex); diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c b/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c index 017a2f10dfbc..a5ec7097e0f6 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -194,8 +194,12 @@ static int pp_hist_lut_cache_params_pipe_v1_7(struct mdp_hist_lut_data *config, return -EINVAL; } - memcpy(&hist_lut_usr_config, config->cfg_payload, - sizeof(struct mdp_hist_lut_data_v1_7)); + if (copy_from_user(&hist_lut_usr_config, + (void __user *) config->cfg_payload, + sizeof(hist_lut_usr_config))) { + pr_err("failed to copy hist lut config\n"); + return -EFAULT; + } hist_lut_cache_data = pipe->pp_res.hist_lut_cfg_payload; if (!hist_lut_cache_data) { @@ -606,8 +610,12 @@ static int pp_pcc_cache_params_pipe_v1_7(struct mdp_pcc_cfg_data *config, return -EINVAL; } - memcpy(&v17_usr_config, config->cfg_payload, - sizeof(v17_usr_config)); + if (copy_from_user(&v17_usr_config, + (void __user *) config->cfg_payload, + sizeof(v17_usr_config))) { + pr_err("failed to copy pcc config\n"); + return -EFAULT; + } if (!(config->ops & MDP_PP_OPS_WRITE)) { pr_debug("write ops not set value of flag is %d\n", @@ -861,8 +869,12 @@ static int pp_igc_lut_cache_params_pipe_v1_7(struct mdp_igc_lut_data *config, goto igc_config_exit; } - memcpy(&v17_usr_config, config->cfg_payload, - sizeof(v17_usr_config)); + if (copy_from_user(&v17_usr_config, + (void __user *) config->cfg_payload, + sizeof(v17_usr_config))) { + pr_err("failed to copy igc usr config\n"); + return -EFAULT; + } if (!(config->ops & MDP_PP_OPS_WRITE)) { pr_debug("op for gamut %d\n", config->ops); @@ -1272,8 +1284,12 @@ static int pp_pa_cache_params_pipe_v1_7(struct mdp_pa_v2_cfg_data *config, return -EINVAL; } - memcpy(&pa_usr_config, config->cfg_payload, - sizeof(struct mdp_pa_data_v1_7)); + if (copy_from_user(&pa_usr_config, + (void __user *) config->cfg_payload, + sizeof(pa_usr_config))) { + pr_err("failed to copy pa usr config\n"); + return -EFAULT; + } pa_cache_data = pipe->pp_res.pa_cfg_payload; if (!pa_cache_data) { diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c index 80dbe83972d7..bb3b4b3fa929 100644 --- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c +++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c @@ -2587,7 +2587,8 @@ int mdss_dsi_post_clkon_cb(void *priv, } if (clk & MDSS_DSI_LINK_CLK) { /* toggle the resync FIFO everytime clock changes */ - if (ctrl->shared_data->phy_rev == DSI_PHY_REV_30) + if ((ctrl->shared_data->phy_rev == DSI_PHY_REV_30) && + !pdata->panel_info.cont_splash_enabled) mdss_dsi_phy_v3_toggle_resync_fifo(ctrl); if (ctrl->ulps) { diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h index 74995a0cdbad..a1d8b04d08ac 100644 --- a/include/sound/apr_audio-v2.h +++ b/include/sound/apr_audio-v2.h @@ -625,6 +625,29 @@ struct audproc_softvolume_params { */ #define AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT 0x00010913 +/* ID of the Channel Mixer module, which is used to configure + * channel-mixer related parameters. + * This module supports the AUDPROC_CHMIXER_PARAM_ID_COEFF parameter ID. + */ +#define AUDPROC_MODULE_ID_CHMIXER 0x00010341 + +/* ID of the Coefficient parameter used by AUDPROC_MODULE_ID_CHMIXER to + *configure the channel mixer weighting coefficients. + */ +#define AUDPROC_CHMIXER_PARAM_ID_COEFF 0x00010342 + +/* Payload of the per-session, per-device parameter data of the + * #ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5 command or + * #ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V6 command. + * Immediately following this structure are param_size bytes of parameter + * data. The structure and size depend on the module_id/param_id pair. + */ +struct adm_pspd_param_data_t { + uint32_t module_id; + uint32_t param_id; + uint16_t param_size; + uint16_t reserved; +} __packed; struct audproc_mfc_output_media_fmt { struct adm_cmd_set_pp_params_v5 params; @@ -3902,6 +3925,14 @@ struct asm_softvolume_params { u32 rampingcurve; } __packed; +struct asm_stream_pan_ctrl_params { + uint16_t num_output_channels; + uint16_t num_input_channels; + uint16_t output_channel_map[8]; + uint16_t input_channel_map[8]; + uint16_t gain[64]; +} __packed; + #define ASM_END_POINT_DEVICE_MATRIX 0 #define PCM_CHANNEL_NULL 0 @@ -7802,6 +7833,48 @@ struct asm_volume_ctrl_lr_chan_gain { /*< Linear gain in Q13 format for the right channel.*/ } __packed; +struct audproc_chmixer_param_coeff { + uint32_t index; + uint16_t num_output_channels; + uint16_t num_input_channels; +} __packed; + + +/* ID of the Multichannel Volume Control parameters used by + * AUDPROC_MODULE_ID_VOL_CTRL. + */ +#define AUDPROC_PARAM_ID_MULTICHANNEL_GAIN 0x00010713 + +/* Payload of the AUDPROC_PARAM_ID_MULTICHANNEL_GAIN channel type/gain + * pairs used by the Volume Control module. + * This structure immediately follows the + * audproc_volume_ctrl_multichannel_gain_t structure. + */ +struct audproc_volume_ctrl_channel_type_gain_pair { + uint8_t channel_type; + /* Channel type for which the gain setting is to be applied. */ + + uint8_t reserved1; + uint8_t reserved2; + uint8_t reserved3; + + uint32_t gain; + /* Gain value for this channel in Q28 format. */ +} __packed; + +/* Payload of the AUDPROC_PARAM_ID_MULTICHANNEL_MUTE parameters used by + * the Volume Control module. + */ +struct audproc_volume_ctrl_multichannel_gain { + uint32_t num_channels; + /* Number of channels for which mute configuration is provided. Any + * channels present in the data for which mute configuration is not + * provided are set to unmute. + */ + + struct audproc_volume_ctrl_channel_type_gain_pair *gain_data; + /* Array of channel type/mute setting pairs. */ +} __packed; /* Structure for the mute configuration parameter for a volume control module. */ diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h index e689e9357012..8c53bb9762ce 100644 --- a/include/sound/q6adm-v2.h +++ b/include/sound/q6adm-v2.h @@ -138,9 +138,13 @@ int adm_get_topology_for_port_copp_idx(int port_id, int copp_idx); int adm_get_indexes_from_copp_id(int copp_id, int *port_idx, int *copp_idx); -int adm_set_stereo_to_custom_stereo(int port_id, int copp_idx, - unsigned int session_id, - char *params, uint32_t params_length); +int adm_set_pspd_matrix_params(int port_id, int copp_idx, + unsigned int session_id, + char *params, uint32_t params_length); + +int adm_set_downmix_params(int port_id, int copp_idx, + unsigned int session_id, char *params, + uint32_t params_length); int adm_get_pp_topo_module_list(int port_id, int copp_idx, int32_t param_length, char *params); diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h index d0dffbd15923..177c2f4da32e 100644 --- a/include/sound/q6asm-v2.h +++ b/include/sound/q6asm-v2.h @@ -611,6 +611,14 @@ int q6asm_set_softvolume(struct audio_client *ac, int q6asm_set_softvolume_v2(struct audio_client *ac, struct asm_softvolume_params *param, int instance); +/* Set panning and MFC params */ +int q6asm_set_mfc_panning_params(struct audio_client *ac, + struct asm_stream_pan_ctrl_params *pan_param); + +/* Set vol gain pair */ +int q6asm_set_vol_ctrl_gain_pair(struct audio_client *ac, + struct asm_stream_pan_ctrl_params *pan_param); + /* Send left-right channel gain */ int q6asm_set_lrgain(struct audio_client *ac, int left_gain, int right_gain); diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 27796c33ca05..d7c1ee7cf0e2 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -184,6 +184,11 @@ ipv4_connected: err = 0; if (IS_ERR(dst)) { err = PTR_ERR(dst); + /* Reset daddr and dport so that udp_v6_early_demux() + * fails to find this socket + */ + memset(&sk->sk_v6_daddr, 0, sizeof(sk->sk_v6_daddr)); + inet->inet_dport = 0; goto out; } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 8a07c63ddccd..a8cabc876348 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -45,6 +45,7 @@ #include <net/tcp_states.h> #include <net/ip6_checksum.h> #include <net/xfrm.h> +#include <net/inet_hashtables.h> #include <net/inet6_hashtables.h> #include <net/busy_poll.h> @@ -964,15 +965,22 @@ static struct sock *__udp6_lib_demux_lookup(struct net *net, int dif) { struct sock *sk; + struct hlist_nulls_node *hnode; + unsigned short hnum = ntohs(loc_port); + unsigned int hash2 = udp6_portaddr_hash(net, loc_addr, hnum); + unsigned int slot2 = hash2 & udp_table.mask; + struct udp_hslot *hslot2 = &udp_table.hash2[slot2]; - rcu_read_lock(); - sk = __udp6_lib_lookup(net, rmt_addr, rmt_port, loc_addr, loc_port, - dif, &udp_table); - if (sk && !atomic_inc_not_zero(&sk->sk_refcnt)) - sk = NULL; - rcu_read_unlock(); + const __portpair ports = INET_COMBINED_PORTS(rmt_port, hnum); - return sk; + udp_portaddr_for_each_entry_rcu(sk, hnode, &hslot2->head) { + if (sk->sk_state == TCP_ESTABLISHED && + INET6_MATCH(sk, net, rmt_addr, loc_addr, ports, dif)) + return sk; + /* Only check first socket in chain */ + break; + } + return NULL; } static void udp_v6_early_demux(struct sk_buff *skb) @@ -997,7 +1005,7 @@ static void udp_v6_early_demux(struct sk_buff *skb) else return; - if (!sk) + if (!sk || !atomic_inc_not_zero_hint(&sk->sk_refcnt, 2)) return; skb->sk = sk; diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c index 24dbbedf0be7..cc89408fcb39 100644 --- a/sound/soc/msm/msm-dai-fe.c +++ b/sound/soc/msm/msm-dai-fe.c @@ -2641,6 +2641,101 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .name = "MultiMedia20", .probe = fe_dai_probe, }, + { + .playback = { + .stream_name = "MultiMedia21 Playback", + .aif_name = "MM_DL21", + .rates = (SNDRV_PCM_RATE_8000_384000 | + SNDRV_PCM_RATE_KNOT), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 384000, + }, + .ops = &msm_fe_Multimedia_dai_ops, + .name = "MultiMedia21", + .probe = fe_dai_probe, + }, + { + .playback = { + .stream_name = "MultiMedia22 Playback", + .aif_name = "MM_DL22", + .rates = (SNDRV_PCM_RATE_8000_384000 | + SNDRV_PCM_RATE_KNOT), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 384000, + }, + .ops = &msm_fe_Multimedia_dai_ops, + .name = "MultiMedia22", + .probe = fe_dai_probe, + }, + { + .playback = { + .stream_name = "MultiMedia23 Playback", + .aif_name = "MM_DL23", + .rates = (SNDRV_PCM_RATE_8000_384000 | + SNDRV_PCM_RATE_KNOT), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 384000, + }, + .ops = &msm_fe_Multimedia_dai_ops, + .name = "MultiMedia23", + .probe = fe_dai_probe, + }, + { + .playback = { + .stream_name = "MultiMedia24 Playback", + .aif_name = "MM_DL24", + .rates = (SNDRV_PCM_RATE_8000_384000 | + SNDRV_PCM_RATE_KNOT), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 384000, + }, + .ops = &msm_fe_Multimedia_dai_ops, + .name = "MultiMedia24", + .probe = fe_dai_probe, + }, + { + .playback = { + .stream_name = "MultiMedia25 Playback", + .aif_name = "MM_DL25", + .rates = (SNDRV_PCM_RATE_8000_384000 | + SNDRV_PCM_RATE_KNOT), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 384000, + }, + .ops = &msm_fe_Multimedia_dai_ops, + .name = "MultiMedia25", + .probe = fe_dai_probe, + }, }; static int msm_fe_dai_dev_probe(struct platform_device *pdev) diff --git a/sound/soc/msm/msm8998.c b/sound/soc/msm/msm8998.c index 0b37e7e073aa..82bdb4af68d8 100644 --- a/sound/soc/msm/msm8998.c +++ b/sound/soc/msm/msm8998.c @@ -5526,6 +5526,91 @@ static struct snd_soc_dai_link msm_common_misc_fe_dai_links[] = { .ignore_pmdown_time = 1, .be_id = MSM_FRONTEND_DAI_MULTIMEDIA18, }, + { + .name = "MultiMedia21", + .stream_name = "MultiMedia21", + .cpu_dai_name = "MultiMedia21", + .platform_name = "msm-pcm-dsp.0", + .dynamic = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE, + .dpcm_playback = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA21, + }, + { + .name = "MultiMedia22", + .stream_name = "MultiMedia22", + .cpu_dai_name = "MultiMedia22", + .platform_name = "msm-pcm-dsp.0", + .dynamic = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE, + .dpcm_playback = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA22, + }, + { + .name = "MultiMedia23", + .stream_name = "MultiMedia23", + .cpu_dai_name = "MultiMedia23", + .platform_name = "msm-pcm-dsp.0", + .dynamic = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE, + .dpcm_playback = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA23, + }, + { + .name = "MultiMedia24", + .stream_name = "MultiMedia24", + .cpu_dai_name = "MultiMedia24", + .platform_name = "msm-pcm-dsp.0", + .dynamic = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE, + .dpcm_playback = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA24, + }, + { + .name = "MultiMedia25", + .stream_name = "MultiMedia25", + .cpu_dai_name = "MultiMedia25", + .platform_name = "msm-pcm-dsp.0", + .dynamic = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE, + .dpcm_playback = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA25, + }, }; static struct snd_soc_dai_link msm_common_be_dai_links[] = { diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c index fa8bdddacef2..3610901addea 100644 --- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c @@ -5147,6 +5147,27 @@ static int msm_dai_tdm_q6_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "%s: Clk Rate from DT file %d\n", __func__, tdm_clk_set.clk_freq_in_hz); + /* initialize static tdm clk attribute to default value */ + tdm_clk_set.clk_attri = Q6AFE_LPASS_CLK_ATTRIBUTE_INVERT_COUPLE_NO; + + /* extract tdm clk attribute into static */ + if (of_find_property(pdev->dev.of_node, + "qcom,msm-cpudai-tdm-clk-attribute", NULL)) { + rc = of_property_read_u16(pdev->dev.of_node, + "qcom,msm-cpudai-tdm-clk-attribute", + &tdm_clk_set.clk_attri); + if (rc) { + dev_err(&pdev->dev, "%s: clk attribute from DT file %s\n", + __func__, "qcom,msm-cpudai-tdm-clk-attribute"); + goto rtn; + } + dev_dbg(&pdev->dev, "%s: clk attribute from DT file %d\n", + __func__, tdm_clk_set.clk_attri); + } else { + dev_dbg(&pdev->dev, "%s: No optional clk attribute found\n", + __func__); + } + /* extract tdm clk src master/slave info into static */ rc = of_property_read_u32(pdev->dev.of_node, "qcom,msm-cpudai-tdm-clk-internal", @@ -6226,6 +6247,41 @@ static int msm_dai_q6_tdm_set_tdm_slot(struct snd_soc_dai *dai, return rc; } +static int msm_dai_q6_tdm_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct msm_dai_q6_tdm_dai_data *dai_data = + dev_get_drvdata(dai->dev); + + switch (dai->id) { + case AFE_PORT_ID_PRIMARY_TDM_RX: + case AFE_PORT_ID_PRIMARY_TDM_RX_1: + case AFE_PORT_ID_PRIMARY_TDM_RX_2: + case AFE_PORT_ID_PRIMARY_TDM_RX_3: + case AFE_PORT_ID_PRIMARY_TDM_RX_4: + case AFE_PORT_ID_PRIMARY_TDM_RX_5: + case AFE_PORT_ID_PRIMARY_TDM_RX_6: + case AFE_PORT_ID_PRIMARY_TDM_RX_7: + case AFE_PORT_ID_PRIMARY_TDM_TX: + case AFE_PORT_ID_PRIMARY_TDM_TX_1: + case AFE_PORT_ID_PRIMARY_TDM_TX_2: + case AFE_PORT_ID_PRIMARY_TDM_TX_3: + case AFE_PORT_ID_PRIMARY_TDM_TX_4: + case AFE_PORT_ID_PRIMARY_TDM_TX_5: + case AFE_PORT_ID_PRIMARY_TDM_TX_6: + case AFE_PORT_ID_PRIMARY_TDM_TX_7: + dai_data->clk_set.clk_freq_in_hz = freq; + break; + default: + return 0; + } + + dev_dbg(dai->dev, "%s: dai id = 0x%x group clk_freq %d\n", + __func__, dai->id, freq); + return 0; +} + + static int msm_dai_q6_tdm_set_channel_map(struct snd_soc_dai *dai, unsigned int tx_num, unsigned int *tx_slot, unsigned int rx_num, unsigned int *rx_slot) @@ -6653,6 +6709,7 @@ static struct snd_soc_dai_ops msm_dai_q6_tdm_ops = { .hw_params = msm_dai_q6_tdm_hw_params, .set_tdm_slot = msm_dai_q6_tdm_set_tdm_slot, .set_channel_map = msm_dai_q6_tdm_set_channel_map, + .set_sysclk = msm_dai_q6_tdm_set_sysclk, .shutdown = msm_dai_q6_tdm_shutdown, }; diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c index 46a3324d2d6b..de769e8b806c 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c @@ -1603,6 +1603,262 @@ done: return ret; } +static int msm_pcm_playback_pan_scale_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret = 0; + int len = 0; + int i = 0; + struct snd_pcm_usr *usr_info = snd_kcontrol_chip(kcontrol); + struct snd_pcm_substream *substream; + struct msm_audio *prtd; + struct asm_stream_pan_ctrl_params pan_param; + + if (!usr_info) { + pr_err("%s: usr_info is null\n", __func__); + ret = -EINVAL; + goto done; + } + + substream = usr_info->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + if (!substream) { + pr_err("%s substream not found\n", __func__); + ret = -EINVAL; + goto done; + } + + if (!substream->runtime) { + pr_err("%s substream runtime not found\n", __func__); + ret = -EINVAL; + goto done; + } + prtd = substream->runtime->private_data; + if (!prtd) { + ret = -EINVAL; + goto done; + } + pan_param.num_output_channels = + ucontrol->value.integer.value[len++]; + if (pan_param.num_output_channels > + PCM_FORMAT_MAX_NUM_CHANNEL) { + ret = -EINVAL; + goto done; + } + pan_param.num_input_channels = + ucontrol->value.integer.value[len++]; + if (pan_param.num_input_channels > + PCM_FORMAT_MAX_NUM_CHANNEL) { + ret = -EINVAL; + goto done; + } + + if (ucontrol->value.integer.value[len++]) { + for (i = 0; i < pan_param.num_output_channels; i++) { + pan_param.output_channel_map[i] = + ucontrol->value.integer.value[len++]; + } + } + if (ucontrol->value.integer.value[len++]) { + for (i = 0; i < pan_param.num_input_channels; i++) { + pan_param.input_channel_map[i] = + ucontrol->value.integer.value[len++]; + } + } + if (ucontrol->value.integer.value[len++]) { + for (i = 0; i < pan_param.num_output_channels * + pan_param.num_input_channels; i++) { + pan_param.gain[i] = + !(ucontrol->value.integer.value[len++] > 0) ? + 0 : 2 << 13; + } + } + + ret = q6asm_set_mfc_panning_params(prtd->audio_client, + &pan_param); + len -= pan_param.num_output_channels * + pan_param.num_input_channels; + for (i = 0; i < pan_param.num_output_channels * + pan_param.num_input_channels; i++) { + pan_param.gain[i] = + ucontrol->value.integer.value[len++]; + } + ret = q6asm_set_vol_ctrl_gain_pair(prtd->audio_client, + &pan_param); + +done: + return ret; +} + +static int msm_pcm_playback_pan_scale_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int msm_add_stream_pan_scale_controls(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_pcm *pcm; + struct snd_pcm_usr *pan_ctl_info; + struct snd_kcontrol *kctl; + const char *playback_mixer_ctl_name = "Audio Stream"; + const char *deviceNo = "NN"; + const char *suffix = "Pan Scale Control"; + int ctl_len, ret = 0; + + if (!rtd) { + pr_err("%s: rtd is NULL\n", __func__); + ret = -EINVAL; + goto done; + } + + pcm = rtd->pcm; + ctl_len = strlen(playback_mixer_ctl_name) + 1 + strlen(deviceNo) + 1 + + strlen(suffix) + 1; + + ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, + NULL, 1, ctl_len, rtd->dai_link->be_id, + &pan_ctl_info); + + if (ret < 0) { + pr_err("%s: failed add ctl %s. err = %d\n", + __func__, suffix, ret); + goto done; + } + kctl = pan_ctl_info->kctl; + snprintf(kctl->id.name, ctl_len, "%s %d %s", playback_mixer_ctl_name, + rtd->pcm->device, suffix); + kctl->put = msm_pcm_playback_pan_scale_ctl_put; + kctl->get = msm_pcm_playback_pan_scale_ctl_get; + pr_debug("%s: Registering new mixer ctl = %s\n", __func__, + kctl->id.name); +done: + return ret; + +} + +static int msm_pcm_playback_dnmix_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int msm_pcm_playback_dnmix_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret = 0; + int len = 0; + int i = 0; + struct snd_pcm_usr *usr_info = snd_kcontrol_chip(kcontrol); + struct snd_pcm_substream *substream; + struct msm_audio *prtd; + struct asm_stream_pan_ctrl_params dnmix_param; + + int be_id = ucontrol->value.integer.value[len]; + int stream_id = 0; + + if (!usr_info) { + pr_err("%s usr_info is null\n", __func__); + ret = -EINVAL; + goto done; + } + substream = usr_info->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + if (!substream) { + pr_err("%s substream not found\n", __func__); + ret = -EINVAL; + goto done; + } + if (!substream->runtime) { + pr_err("%s substream runtime not found\n", __func__); + ret = -EINVAL; + goto done; + } + prtd = substream->runtime->private_data; + if (!prtd) { + ret = -EINVAL; + goto done; + } + stream_id = prtd->audio_client->session; + dnmix_param.num_output_channels = + ucontrol->value.integer.value[len++]; + if (dnmix_param.num_output_channels > + PCM_FORMAT_MAX_NUM_CHANNEL) { + ret = -EINVAL; + goto done; + } + dnmix_param.num_input_channels = + ucontrol->value.integer.value[len++]; + if (dnmix_param.num_input_channels > + PCM_FORMAT_MAX_NUM_CHANNEL) { + ret = -EINVAL; + goto done; + } + + if (ucontrol->value.integer.value[len++]) { + for (i = 0; i < dnmix_param.num_output_channels; i++) { + dnmix_param.output_channel_map[i] = + ucontrol->value.integer.value[len++]; + } + } + if (ucontrol->value.integer.value[len++]) { + for (i = 0; i < dnmix_param.num_input_channels; i++) { + dnmix_param.input_channel_map[i] = + ucontrol->value.integer.value[len++]; + } + } + if (ucontrol->value.integer.value[len++]) { + for (i = 0; i < dnmix_param.num_output_channels * + dnmix_param.num_input_channels; i++) { + dnmix_param.gain[i] = + ucontrol->value.integer.value[len++]; + } + } + msm_routing_set_downmix_control_data(be_id, + stream_id, + &dnmix_param); + +done: + return ret; +} + +static int msm_add_device_down_mix_controls(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_pcm *pcm; + struct snd_pcm_usr *usr_info; + struct snd_kcontrol *kctl; + const char *playback_mixer_ctl_name = "Audio Device"; + const char *deviceNo = "NN"; + const char *suffix = "Downmix Control"; + int ctl_len, ret = 0; + + if (!rtd) { + pr_err("%s: rtd is NULL\n", __func__); + ret = -EINVAL; + goto done; + } + + pcm = rtd->pcm; + ctl_len = strlen(playback_mixer_ctl_name) + 1 + + strlen(deviceNo) + 1 + strlen(suffix) + 1; + ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, + NULL, 1, ctl_len, rtd->dai_link->be_id, + &usr_info); + if (ret < 0) { + pr_err("%s: downmix control add failed: %d\n", + __func__, ret); + goto done; + } + + kctl = usr_info->kctl; + snprintf(kctl->id.name, ctl_len, "%s %d %s", + playback_mixer_ctl_name, rtd->pcm->device, suffix); + kctl->put = msm_pcm_playback_dnmix_ctl_put; + kctl->get = msm_pcm_playback_dnmix_ctl_get; + pr_debug("%s: downmix control name = %s\n", + __func__, playback_mixer_ctl_name); +done: + return ret; +} + static int msm_pcm_capture_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1719,6 +1975,14 @@ static int msm_pcm_add_controls(struct snd_soc_pcm_runtime *rtd) if (ret) pr_err("%s: pcm add app type controls failed:%d\n", __func__, ret); + ret = msm_add_stream_pan_scale_controls(rtd); + if (ret) + pr_err("%s: pcm add pan scale controls failed:%d\n", + __func__, ret); + ret = msm_add_device_down_mix_controls(rtd); + if (ret) + pr_err("%s: pcm add dnmix controls failed:%d\n", + __func__, ret); return ret; } diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index 974d4a582540..b64bd7ed8fc7 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -35,6 +35,8 @@ #include <sound/audio_cal_utils.h> #include <sound/audio_effects.h> #include <sound/hwdep.h> +#include <sound/q6adm-v2.h> +#include <sound/apr_audio-v2.h> #include "msm-pcm-routing-v2.h" #include "msm-pcm-routing-devdep.h" @@ -4090,6 +4092,21 @@ static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_SLIMBUS_0_RX, MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia23", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_FRONTEND_DAI_MULTIMEDIA23, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia24", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_FRONTEND_DAI_MULTIMEDIA24, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia25", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_FRONTEND_DAI_MULTIMEDIA25, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new mi2s_rx_mixer_controls[] = { @@ -4612,6 +4629,21 @@ static const struct snd_kcontrol_new hdmi_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_HDMI_RX, MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia23", MSM_BACKEND_DAI_HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA23, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia24", MSM_BACKEND_DAI_HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA24, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia25", MSM_BACKEND_DAI_HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA25, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new display_port_mixer_controls[] = { @@ -4760,6 +4792,21 @@ static const struct snd_kcontrol_new slimbus_6_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_SLIMBUS_6_RX, MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_SLIMBUS_6_RX, + MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_SLIMBUS_6_RX, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia23", MSM_BACKEND_DAI_SLIMBUS_6_RX, + MSM_FRONTEND_DAI_MULTIMEDIA23, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia24", MSM_BACKEND_DAI_SLIMBUS_6_RX, + MSM_FRONTEND_DAI_MULTIMEDIA24, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia25", MSM_BACKEND_DAI_SLIMBUS_6_RX, + MSM_FRONTEND_DAI_MULTIMEDIA25, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new slimbus_7_rx_mixer_controls[] = { @@ -4811,6 +4858,21 @@ static const struct snd_kcontrol_new slimbus_7_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_SLIMBUS_7_RX, MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_SLIMBUS_7_RX, + MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_SLIMBUS_7_RX, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia23", MSM_BACKEND_DAI_SLIMBUS_7_RX, + MSM_FRONTEND_DAI_MULTIMEDIA23, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia24", MSM_BACKEND_DAI_SLIMBUS_7_RX, + MSM_FRONTEND_DAI_MULTIMEDIA24, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia25", MSM_BACKEND_DAI_SLIMBUS_7_RX, + MSM_FRONTEND_DAI_MULTIMEDIA25, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new usb_audio_rx_mixer_controls[] = { @@ -9797,6 +9859,22 @@ static const struct snd_kcontrol_new quat_tdm_rx_0_port_mixer_controls[] = { MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer, msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_0", MSM_BACKEND_DAI_QUAT_TDM_RX_0, + MSM_BACKEND_DAI_PRI_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_1", MSM_BACKEND_DAI_QUAT_TDM_RX_0, + MSM_BACKEND_DAI_PRI_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_QUAT_TDM_RX_0, + MSM_BACKEND_DAI_PRI_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_QUAT_TDM_RX_0, + MSM_BACKEND_DAI_PRI_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_QUAT_TDM_RX_0, MSM_BACKEND_DAI_TERT_TDM_TX_0, 1, 0, msm_routing_get_port_mixer, @@ -9864,6 +9942,22 @@ static const struct snd_kcontrol_new quat_tdm_rx_1_port_mixer_controls[] = { MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer, msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_0", MSM_BACKEND_DAI_QUAT_TDM_RX_1, + MSM_BACKEND_DAI_PRI_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_1", MSM_BACKEND_DAI_QUAT_TDM_RX_1, + MSM_BACKEND_DAI_PRI_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_QUAT_TDM_RX_1, + MSM_BACKEND_DAI_PRI_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_QUAT_TDM_RX_1, + MSM_BACKEND_DAI_PRI_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_QUAT_TDM_RX_1, MSM_BACKEND_DAI_TERT_TDM_TX_0, 1, 0, msm_routing_get_port_mixer, @@ -9931,6 +10025,22 @@ static const struct snd_kcontrol_new quat_tdm_rx_2_port_mixer_controls[] = { MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer, msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_0", MSM_BACKEND_DAI_QUAT_TDM_RX_2, + MSM_BACKEND_DAI_PRI_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_1", MSM_BACKEND_DAI_QUAT_TDM_RX_2, + MSM_BACKEND_DAI_PRI_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_QUAT_TDM_RX_2, + MSM_BACKEND_DAI_PRI_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_QUAT_TDM_RX_2, + MSM_BACKEND_DAI_PRI_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_QUAT_TDM_RX_2, MSM_BACKEND_DAI_TERT_TDM_TX_0, 1, 0, msm_routing_get_port_mixer, @@ -9998,6 +10108,22 @@ static const struct snd_kcontrol_new quat_tdm_rx_3_port_mixer_controls[] = { MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer, msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_0", MSM_BACKEND_DAI_QUAT_TDM_RX_3, + MSM_BACKEND_DAI_PRI_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_1", MSM_BACKEND_DAI_QUAT_TDM_RX_3, + MSM_BACKEND_DAI_PRI_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_QUAT_TDM_RX_3, + MSM_BACKEND_DAI_PRI_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_QUAT_TDM_RX_3, + MSM_BACKEND_DAI_PRI_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_QUAT_TDM_RX_3, MSM_BACKEND_DAI_TERT_TDM_TX_0, 1, 0, msm_routing_get_port_mixer, @@ -11314,6 +11440,11 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_AIF_IN("MM_DL15", "MultiMedia15 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("MM_DL16", "MultiMedia16 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("MM_DL20", "MultiMedia20 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL21", "MultiMedia21 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL22", "MultiMedia22 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL23", "MultiMedia23 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL24", "MultiMedia24 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL25", "MultiMedia25 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("VOIP_DL", "VoIP Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0), @@ -12450,6 +12581,11 @@ static const struct snd_soc_dapm_route intercon[] = { {"SLIMBUS_0_RX Audio Mixer", "MultiMedia14", "MM_DL14"}, {"SLIMBUS_0_RX Audio Mixer", "MultiMedia15", "MM_DL15"}, {"SLIMBUS_0_RX Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"SLIMBUS_0_RX Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"SLIMBUS_0_RX Audio Mixer", "MultiMedia22", "MM_DL22"}, + {"SLIMBUS_0_RX Audio Mixer", "MultiMedia23", "MM_DL23"}, + {"SLIMBUS_0_RX Audio Mixer", "MultiMedia24", "MM_DL24"}, + {"SLIMBUS_0_RX Audio Mixer", "MultiMedia25", "MM_DL25"}, {"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Audio Mixer"}, {"SLIMBUS_2_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, @@ -12504,6 +12640,11 @@ static const struct snd_soc_dapm_route intercon[] = { {"HDMI Mixer", "MultiMedia14", "MM_DL14"}, {"HDMI Mixer", "MultiMedia15", "MM_DL15"}, {"HDMI Mixer", "MultiMedia16", "MM_DL16"}, + {"HDMI Mixer", "MultiMedia21", "MM_DL21"}, + {"HDMI Mixer", "MultiMedia22", "MM_DL22"}, + {"HDMI Mixer", "MultiMedia23", "MM_DL23"}, + {"HDMI Mixer", "MultiMedia24", "MM_DL24"}, + {"HDMI Mixer", "MultiMedia25", "MM_DL25"}, {"HDMI", NULL, "HDMI Mixer"}, {"DISPLAY_PORT Mixer", "MultiMedia1", "MM_DL1"}, @@ -12575,6 +12716,11 @@ static const struct snd_soc_dapm_route intercon[] = { {"SLIMBUS_6_RX Audio Mixer", "MultiMedia14", "MM_DL14"}, {"SLIMBUS_6_RX Audio Mixer", "MultiMedia15", "MM_DL15"}, {"SLIMBUS_6_RX Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"SLIMBUS_6_RX Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"SLIMBUS_6_RX Audio Mixer", "MultiMedia22", "MM_DL22"}, + {"SLIMBUS_6_RX Audio Mixer", "MultiMedia23", "MM_DL23"}, + {"SLIMBUS_6_RX Audio Mixer", "MultiMedia24", "MM_DL24"}, + {"SLIMBUS_6_RX Audio Mixer", "MultiMedia25", "MM_DL25"}, {"SLIMBUS_6_RX", NULL, "SLIMBUS_6_RX Audio Mixer"}, {"SLIMBUS_7_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, @@ -12593,6 +12739,11 @@ static const struct snd_soc_dapm_route intercon[] = { {"SLIMBUS_7_RX Audio Mixer", "MultiMedia14", "MM_DL14"}, {"SLIMBUS_7_RX Audio Mixer", "MultiMedia15", "MM_DL15"}, {"SLIMBUS_7_RX Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"SLIMBUS_7_RX Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"SLIMBUS_7_RX Audio Mixer", "MultiMedia22", "MM_DL22"}, + {"SLIMBUS_7_RX Audio Mixer", "MultiMedia23", "MM_DL23"}, + {"SLIMBUS_7_RX Audio Mixer", "MultiMedia24", "MM_DL24"}, + {"SLIMBUS_7_RX Audio Mixer", "MultiMedia25", "MM_DL25"}, {"SLIMBUS_7_RX", NULL, "SLIMBUS_7_RX Audio Mixer"}, {"USB_AUDIO_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, @@ -14460,6 +14611,10 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_TDM_RX_0 Port Mixer", "AFE_PCM_TX", "PCM_TX"}, {"QUAT_TDM_RX_0 Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, {"QUAT_TDM_RX_0 Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"}, + {"QUAT_TDM_RX_0 Port Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, + {"QUAT_TDM_RX_0 Port Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, + {"QUAT_TDM_RX_0 Port Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"QUAT_TDM_RX_0 Port Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, {"QUAT_TDM_RX_0 Port Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"}, {"QUAT_TDM_RX_0 Port Mixer", "TERT_TDM_TX_1", "TERT_TDM_TX_1"}, {"QUAT_TDM_RX_0 Port Mixer", "TERT_TDM_TX_2", "TERT_TDM_TX_2"}, @@ -14478,6 +14633,10 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_TDM_RX_1 Port Mixer", "AFE_PCM_TX", "PCM_TX"}, {"QUAT_TDM_RX_1 Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, {"QUAT_TDM_RX_1 Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"}, + {"QUAT_TDM_RX_1 Port Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, + {"QUAT_TDM_RX_1 Port Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, + {"QUAT_TDM_RX_1 Port Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"QUAT_TDM_RX_1 Port Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, {"QUAT_TDM_RX_1 Port Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"}, {"QUAT_TDM_RX_1 Port Mixer", "TERT_TDM_TX_1", "TERT_TDM_TX_1"}, {"QUAT_TDM_RX_1 Port Mixer", "TERT_TDM_TX_2", "TERT_TDM_TX_2"}, @@ -14496,6 +14655,10 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_TDM_RX_2 Port Mixer", "AFE_PCM_TX", "PCM_TX"}, {"QUAT_TDM_RX_2 Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, {"QUAT_TDM_RX_2 Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"}, + {"QUAT_TDM_RX_2 Port Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, + {"QUAT_TDM_RX_2 Port Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, + {"QUAT_TDM_RX_2 Port Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"QUAT_TDM_RX_2 Port Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, {"QUAT_TDM_RX_2 Port Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"}, {"QUAT_TDM_RX_2 Port Mixer", "TERT_TDM_TX_1", "TERT_TDM_TX_1"}, {"QUAT_TDM_RX_2 Port Mixer", "TERT_TDM_TX_2", "TERT_TDM_TX_2"}, @@ -14514,6 +14677,10 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_TDM_RX_3 Port Mixer", "AFE_PCM_TX", "PCM_TX"}, {"QUAT_TDM_RX_3 Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, {"QUAT_TDM_RX_3 Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"}, + {"QUAT_TDM_RX_3 Port Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, + {"QUAT_TDM_RX_3 Port Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, + {"QUAT_TDM_RX_3 Port Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"QUAT_TDM_RX_3 Port Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, {"QUAT_TDM_RX_3 Port Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"}, {"QUAT_TDM_RX_3 Port Mixer", "TERT_TDM_TX_1", "TERT_TDM_TX_1"}, {"QUAT_TDM_RX_3 Port Mixer", "TERT_TDM_TX_2", "TERT_TDM_TX_2"}, @@ -15486,6 +15653,93 @@ static struct snd_pcm_ops msm_routing_pcm_ops = { .prepare = msm_pcm_routing_prepare, }; +int msm_routing_set_downmix_control_data(int be_id, int session_id, + struct asm_stream_pan_ctrl_params *dnmix_param) +{ + int i, rc = 0; + struct adm_pspd_param_data_t data; + struct audproc_chmixer_param_coeff dnmix_cfg; + uint16_t variable_payload = 0; + char *adm_params = NULL; + int port_id, copp_idx = 0; + uint32_t params_length = 0; + + if (be_id >= MSM_BACKEND_DAI_MAX) { + rc = -EINVAL; + return rc; + } + port_id = msm_bedais[be_id].port_id; + copp_idx = adm_get_default_copp_idx(port_id); + pr_debug("%s: port_id - %d, copp_idx %d session id - %d\n", + __func__, port_id, copp_idx, session_id); + + variable_payload = dnmix_param->num_output_channels * sizeof(uint16_t)+ + dnmix_param->num_input_channels * sizeof(uint16_t) + + dnmix_param->num_output_channels * sizeof(uint16_t) * + dnmix_param->num_input_channels * sizeof(uint16_t); + i = (variable_payload % sizeof(uint32_t)); + variable_payload += (i == 0) ? 0 : sizeof(uint32_t) - i; + + params_length = variable_payload + + sizeof(struct adm_pspd_param_data_t) + + sizeof(struct audproc_chmixer_param_coeff); + adm_params = kzalloc(params_length, GFP_KERNEL); + if (!adm_params) { + rc = -ENOMEM; + goto end; + } + + data.module_id = AUDPROC_MODULE_ID_CHMIXER; + data.param_id = AUDPROC_CHMIXER_PARAM_ID_COEFF; + data.param_size = sizeof(struct audproc_chmixer_param_coeff) + + variable_payload; + data.reserved = 0; + memcpy((u8 *)adm_params, &data, sizeof(struct adm_pspd_param_data_t)); + + dnmix_cfg.index = 0; + dnmix_cfg.num_output_channels = dnmix_param->num_output_channels; + dnmix_cfg.num_input_channels = dnmix_param->num_input_channels; + memcpy(((u8 *)adm_params + + sizeof(struct adm_pspd_param_data_t)), + &dnmix_cfg, sizeof(struct audproc_chmixer_param_coeff)); + + memcpy(((u8 *)adm_params + + sizeof(struct adm_pspd_param_data_t) + + sizeof(struct audproc_chmixer_param_coeff)), + dnmix_param->output_channel_map, + dnmix_param->num_output_channels * sizeof(uint16_t)); + memcpy(((u8 *)adm_params + + sizeof(struct adm_pspd_param_data_t) + + sizeof(struct audproc_chmixer_param_coeff) + + dnmix_param->num_output_channels * sizeof(uint16_t)), + dnmix_param->input_channel_map, + dnmix_param->num_input_channels * sizeof(uint16_t)); + memcpy(((u8 *)adm_params + + sizeof(struct adm_pspd_param_data_t) + + sizeof(struct audproc_chmixer_param_coeff) + + (dnmix_param->num_output_channels * sizeof(uint16_t)) + + (dnmix_param->num_input_channels * sizeof(uint16_t))), + dnmix_param->gain, + (dnmix_param->num_output_channels * sizeof(uint16_t)) * + (dnmix_param->num_input_channels * sizeof(uint16_t))); + + if (params_length) { + rc = adm_set_pspd_matrix_params(port_id, + copp_idx, + session_id, + adm_params, + params_length); + if (rc) { + pr_err("%s: send params failed rc=%d\n", __func__, rc); + rc = -EINVAL; + } + } +end: + kfree(adm_params); + return rc; +} + + /* Not used but frame seems to require it */ static int msm_routing_probe(struct snd_soc_platform *platform) { diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h index 19e726001d25..fa948abd1b4c 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h @@ -193,6 +193,11 @@ enum { MSM_FRONTEND_DAI_MULTIMEDIA18, MSM_FRONTEND_DAI_MULTIMEDIA19, MSM_FRONTEND_DAI_MULTIMEDIA20, + MSM_FRONTEND_DAI_MULTIMEDIA21, + MSM_FRONTEND_DAI_MULTIMEDIA22, + MSM_FRONTEND_DAI_MULTIMEDIA23, + MSM_FRONTEND_DAI_MULTIMEDIA24, + MSM_FRONTEND_DAI_MULTIMEDIA25, MSM_FRONTEND_DAI_CS_VOICE, MSM_FRONTEND_DAI_VOIP, MSM_FRONTEND_DAI_AFE_RX, @@ -218,8 +223,8 @@ enum { MSM_FRONTEND_DAI_MAX, }; -#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA20 + 1) -#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA20 +#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA25 + 1) +#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA25 enum { MSM_BACKEND_DAI_PRI_I2S_RX = 0, @@ -483,4 +488,6 @@ int msm_pcm_routing_reg_stream_app_type_cfg( int msm_pcm_routing_get_stream_app_type_cfg( int fedai_id, int session_type, int *be_id, struct msm_pcm_stream_app_type_cfg *cfg_data); +int msm_routing_set_downmix_control_data(int be_id, int session_id, + struct asm_stream_pan_ctrl_params *pan_param); #endif /*_MSM_PCM_H*/ diff --git a/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c index cac28f43e5ae..65f5167d9dee 100644 --- a/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c +++ b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c @@ -298,11 +298,11 @@ int msm_qti_pp_send_stereo_to_custom_stereo_cmd(int port_id, int copp_idx, *update_params_value16++ = op_FR_ip_FR_weight; avail_length = avail_length - (4 * sizeof(uint16_t)); if (params_length) { - rc = adm_set_stereo_to_custom_stereo(port_id, - copp_idx, - session_id, - params_value, - params_length); + rc = adm_set_pspd_matrix_params(port_id, + copp_idx, + session_id, + params_value, + params_length); if (rc) { pr_err("%s: send params failed rc=%d\n", __func__, rc); kfree(params_value); diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c index 28aaf2172221..4aad16db3e0f 100644 --- a/sound/soc/msm/qdsp6v2/q6adm.c +++ b/sound/soc/msm/qdsp6v2/q6adm.c @@ -781,9 +781,9 @@ fail_cmd: return ret; } -int adm_set_stereo_to_custom_stereo(int port_id, int copp_idx, - unsigned int session_id, char *params, - uint32_t params_length) +int adm_set_pspd_matrix_params(int port_id, int copp_idx, + unsigned int session_id, char *params, + uint32_t params_length) { struct adm_cmd_set_pspd_mtmx_strtr_params_v5 *adm_params = NULL; int sz, rc = 0, port_idx; diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 44e5b01b1ccb..d3cff9fccf59 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -44,7 +44,7 @@ #define TRUE 0x01 #define FALSE 0x00 #define SESSION_MAX 8 - +#define ASM_MAX_CHANNELS 8 enum { ASM_TOPOLOGY_CAL = 0, ASM_CUSTOM_TOP_CAL, @@ -7419,6 +7419,296 @@ int q6asm_set_softvolume_v2(struct audio_client *ac, return __q6asm_set_softvolume(ac, softvol_param, instance); } +int q6asm_set_vol_ctrl_gain_pair(struct audio_client *ac, + struct asm_stream_pan_ctrl_params *pan_param) +{ + int sz = 0; + int rc = 0; + int i = 0; + int32_t ch = 0; + struct apr_hdr hdr; + struct audproc_volume_ctrl_channel_type_gain_pair + gain_data[ASM_MAX_CHANNELS]; + struct asm_stream_cmd_set_pp_params_v2 payload_params; + struct asm_stream_param_data_v2 data; + uint16_t *asm_params = NULL; + + if (ac == NULL) { + pr_err("%s: ac is NULL\n", __func__); + rc = -EINVAL; + goto fail; + } + if (ac->apr == NULL) { + dev_err(ac->dev, "%s: ac apr handle NULL\n", __func__); + rc = -EINVAL; + goto fail; + } + + sz = sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2) + + sizeof(struct asm_stream_param_data_v2) + + sizeof(uint32_t) + + (sizeof(struct audproc_volume_ctrl_channel_type_gain_pair) * + ASM_MAX_CHANNELS); + asm_params = kzalloc(sz, GFP_KERNEL); + if (!asm_params) { + rc = -ENOMEM; + goto fail; + } + + q6asm_add_hdr_async(ac, &hdr, sz, TRUE); + atomic_set(&ac->cmd_state_pp, -1); + + hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2; + memcpy(((u8 *)asm_params), &hdr, sizeof(struct apr_hdr)); + + payload_params.data_payload_addr_lsw = 0; + payload_params.data_payload_addr_msw = 0; + payload_params.mem_map_handle = 0; + payload_params.data_payload_size = + sizeof(struct asm_stream_param_data_v2) + + sizeof(uint32_t) + + (sizeof(struct audproc_volume_ctrl_channel_type_gain_pair) * + ASM_MAX_CHANNELS); + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr)), + &payload_params, + sizeof(struct asm_stream_cmd_set_pp_params_v2)); + + data.module_id = AUDPROC_MODULE_ID_VOL_CTRL; + data.param_id = AUDPROC_PARAM_ID_MULTICHANNEL_GAIN; + data.param_size = sizeof(uint32_t) + + (sizeof(struct audproc_volume_ctrl_channel_type_gain_pair) * + ASM_MAX_CHANNELS); + data.reserved = 0; + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2)), + &data, sizeof(struct asm_stream_param_data_v2)); + + ch = pan_param->num_output_channels; + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2) + + sizeof(struct asm_stream_param_data_v2)), + &ch, + sizeof(uint32_t)); + + memset(gain_data, 0, + ASM_MAX_CHANNELS * + sizeof(struct audproc_volume_ctrl_channel_type_gain_pair)); + for (i = 0; i < pan_param->num_output_channels; i++) { + gain_data[i].channel_type = + pan_param->output_channel_map[i]; + gain_data[i].gain = pan_param->gain[i]; + } + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2) + + sizeof(struct asm_stream_param_data_v2) + + sizeof(uint32_t)), + gain_data, + ASM_MAX_CHANNELS * + sizeof(struct audproc_volume_ctrl_channel_type_gain_pair)); + + rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params); + if (rc < 0) { + pr_err("%s: set-params send failed paramid[0x%x] rc %d\n", + __func__, data.param_id, rc); + goto done; + } + + rc = wait_event_timeout(ac->cmd_wait, + (atomic_read(&ac->cmd_state_pp) >= 0), 5 * HZ); + if (!rc) { + pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__, + data.param_id); + rc = -EINVAL; + goto done; + } + if (atomic_read(&ac->cmd_state_pp) > 0) { + pr_err("%s: DSP returned error[%d], set-params paramid[0x%x]\n", + __func__, atomic_read(&ac->cmd_state_pp), + data.param_id); + rc = -EINVAL; + goto done; + } + rc = 0; +done: + kfree(asm_params); +fail: + return rc; +} + +int q6asm_set_mfc_panning_params(struct audio_client *ac, + struct asm_stream_pan_ctrl_params *pan_param) +{ + int sz, rc, i; + struct audproc_mfc_output_media_fmt mfc_cfg; + struct apr_hdr hdr; + struct asm_stream_cmd_set_pp_params_v2 payload_params; + struct asm_stream_param_data_v2 data; + struct audproc_chmixer_param_coeff pan_cfg; + uint16_t variable_payload = 0; + uint16_t *asm_params = NULL; + + sz = rc = i = 0; + if (ac == NULL) { + pr_err("%s: ac handle NULL\n", __func__); + rc = -EINVAL; + goto fail_cmd1; + } + if (ac->apr == NULL) { + pr_err("%s: ac apr handle NULL\n", __func__); + rc = -EINVAL; + goto fail_cmd1; + } + + sz = sizeof(struct audproc_mfc_output_media_fmt); + q6asm_add_hdr_async(ac, &mfc_cfg.params.hdr, sz, TRUE); + atomic_set(&ac->cmd_state_pp, -1); + mfc_cfg.params.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2; + mfc_cfg.params.payload_addr_lsw = 0; + mfc_cfg.params.payload_addr_msw = 0; + mfc_cfg.params.mem_map_handle = 0; + mfc_cfg.params.payload_size = sizeof(mfc_cfg) - sizeof(mfc_cfg.params); + mfc_cfg.data.module_id = AUDPROC_MODULE_ID_MFC; + mfc_cfg.data.param_id = AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT; + mfc_cfg.data.param_size = mfc_cfg.params.payload_size - + sizeof(mfc_cfg.data); + mfc_cfg.data.reserved = 0; + mfc_cfg.sampling_rate = 0; + mfc_cfg.bits_per_sample = 0; + mfc_cfg.num_channels = pan_param->num_output_channels; + for (i = 0; i < mfc_cfg.num_channels; i++) + mfc_cfg.channel_type[i] = pan_param->output_channel_map[i]; + + rc = apr_send_pkt(ac->apr, (uint32_t *) &mfc_cfg); + if (rc < 0) { + pr_err("%s: set-params send failed paramid[0x%x] rc %d\n", + __func__, mfc_cfg.data.param_id, rc); + rc = -EINVAL; + goto fail_cmd1; + } + + rc = wait_event_timeout(ac->cmd_wait, + (atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ); + if (!rc) { + pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__, + mfc_cfg.data.param_id); + rc = -ETIMEDOUT; + goto fail_cmd1; + } + if (atomic_read(&ac->cmd_state_pp) > 0) { + pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n", + __func__, adsp_err_get_err_str( + atomic_read(&ac->cmd_state_pp)), + mfc_cfg.data.param_id); + rc = adsp_err_get_lnx_err_code( + atomic_read(&ac->cmd_state_pp)); + goto fail_cmd1; + } + + variable_payload = pan_param->num_output_channels * sizeof(uint16_t)+ + pan_param->num_input_channels * sizeof(uint16_t) + + pan_param->num_output_channels * sizeof(uint16_t) * + pan_param->num_input_channels * sizeof(uint16_t); + i = (variable_payload % sizeof(uint32_t)); + variable_payload += (i == 0) ? 0 : sizeof(uint32_t) - i; + sz = sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2) + + sizeof(struct asm_stream_param_data_v2) + + sizeof(struct audproc_chmixer_param_coeff) + + variable_payload; + + asm_params = kzalloc(sz, GFP_KERNEL); + if (!asm_params) { + rc = -ENOMEM; + goto fail_cmd1; + } + + q6asm_add_hdr_async(ac, &hdr, sz, TRUE); + atomic_set(&ac->cmd_state_pp, -1); + hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2; + memcpy(((u8 *)asm_params), &hdr, sizeof(struct apr_hdr)); + + payload_params.data_payload_addr_lsw = 0; + payload_params.data_payload_addr_msw = 0; + payload_params.mem_map_handle = 0; + payload_params.data_payload_size = + sizeof(struct audproc_chmixer_param_coeff) + + variable_payload + sizeof(struct asm_stream_param_data_v2); + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr)), + &payload_params, + sizeof(struct asm_stream_cmd_set_pp_params_v2)); + + data.module_id = AUDPROC_MODULE_ID_MFC; + data.param_id = AUDPROC_CHMIXER_PARAM_ID_COEFF; + data.param_size = sizeof(struct audproc_chmixer_param_coeff) + + variable_payload; + data.reserved = 0; + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2)), + &data, sizeof(struct asm_stream_param_data_v2)); + + pan_cfg.index = 0; + pan_cfg.num_output_channels = pan_param->num_output_channels; + pan_cfg.num_input_channels = pan_param->num_input_channels; + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2) + + sizeof(struct asm_stream_param_data_v2)), + &pan_cfg, sizeof(struct audproc_chmixer_param_coeff)); + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2) + + sizeof(struct asm_stream_param_data_v2) + + sizeof(struct audproc_chmixer_param_coeff)), + pan_param->output_channel_map, + pan_param->num_output_channels * sizeof(uint16_t)); + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2) + + sizeof(struct asm_stream_param_data_v2) + + sizeof(struct audproc_chmixer_param_coeff) + + pan_param->num_output_channels * sizeof(uint16_t)), + pan_param->input_channel_map, + pan_param->num_input_channels * sizeof(uint16_t)); + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2) + + sizeof(struct asm_stream_param_data_v2) + + sizeof(struct audproc_chmixer_param_coeff) + + (pan_param->num_output_channels * sizeof(uint16_t)) + + (pan_param->num_input_channels * sizeof(uint16_t))), + pan_param->gain, + (pan_param->num_output_channels * sizeof(uint16_t)) * + (pan_param->num_input_channels * sizeof(uint16_t))); + + rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params); + if (rc < 0) { + pr_err("%s: set-params send failed paramid[0x%x] rc %d\n", + __func__, data.param_id, rc); + rc = -EINVAL; + goto fail_cmd2; + } + + rc = wait_event_timeout(ac->cmd_wait, + (atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ); + if (!rc) { + pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__, + data.param_id); + rc = -ETIMEDOUT; + goto fail_cmd2; + } + if (atomic_read(&ac->cmd_state_pp) > 0) { + pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n", + __func__, adsp_err_get_err_str( + atomic_read(&ac->cmd_state_pp)), + data.param_id); + rc = adsp_err_get_lnx_err_code( + atomic_read(&ac->cmd_state_pp)); + goto fail_cmd2; + } + rc = 0; +fail_cmd2: + kfree(asm_params); +fail_cmd1: + return rc; +} + int q6asm_equalizer(struct audio_client *ac, void *eq_p) { struct asm_eq_params eq; |
