diff options
99 files changed, 2464 insertions, 773 deletions
diff --git a/arch/arm/boot/dts/qcom/apq8096-dragonboard.dtsi b/arch/arm/boot/dts/qcom/apq8096-dragonboard.dtsi index e731c7edd518..1ea94d546542 100644 --- a/arch/arm/boot/dts/qcom/apq8096-dragonboard.dtsi +++ b/arch/arm/boot/dts/qcom/apq8096-dragonboard.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 @@ -13,6 +13,7 @@ #include "msm8996-pinctrl.dtsi" #include "apq8096-camera-sensor-dragonboard.dtsi" #include "apq8096-ba.dtsi" +#include "msm8996-mdss-panels.dtsi" / { bluetooth: bt_qca6174 { @@ -326,8 +327,6 @@ }; }; -#include "msm8996-sde-display.dtsi" - &dsi_hx8379a_fwvga_truly_vid { qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm"; qcom,mdss-dsi-bl-min-level = <1>; diff --git a/arch/arm/boot/dts/qcom/apq8096-v2-auto-dragonboard.dts b/arch/arm/boot/dts/qcom/apq8096-v2-auto-dragonboard.dts index d200bf718de2..575b85d8d111 100644 --- a/arch/arm/boot/dts/qcom/apq8096-v2-auto-dragonboard.dts +++ b/arch/arm/boot/dts/qcom/apq8096-v2-auto-dragonboard.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015,2018, 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 @@ -14,6 +14,7 @@ /dts-v1/; #include "apq8096-v2.dtsi" +#include "msm8996-sde.dtsi" #include "apq8096-auto-dragonboard.dtsi" / { diff --git a/arch/arm/boot/dts/qcom/apq8096-v3-auto-dragonboard.dts b/arch/arm/boot/dts/qcom/apq8096-v3-auto-dragonboard.dts index 0f8e148ec3ab..7028d372dd04 100644 --- a/arch/arm/boot/dts/qcom/apq8096-v3-auto-dragonboard.dts +++ b/arch/arm/boot/dts/qcom/apq8096-v3-auto-dragonboard.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015,2018, 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 @@ -14,6 +14,7 @@ /dts-v1/; #include "apq8096-v3.dtsi" +#include "msm8996-sde.dtsi" #include "apq8096-auto-dragonboard.dtsi" / { diff --git a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi index 9e14211bdac8..2adfb8b749eb 100644 --- a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi @@ -13,6 +13,7 @@ #include "msm8996-pinctrl.dtsi" #include "msm8996-camera-sensor-adp.dtsi" #include "msm8996-wsa881x.dtsi" +#include "msm8996-sde.dtsi" / { bluetooth: bt_qca6174 { diff --git a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi index 0902320d78ce..7cbc09767f62 100644 --- a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi @@ -13,6 +13,7 @@ #include "msm8996-pinctrl.dtsi" #include "msm8996-camera-sensor-auto-cdp.dtsi" #include "msm8996-wsa881x.dtsi" +#include "msm8996-sde.dtsi" / { bluetooth: bt_qca6174 { @@ -694,6 +695,8 @@ vdd-ntn-hsic-supply = <&pm8994_l25>; vdd-ntn-pci-supply = <&pm8994_s4>; vdd-ntn-io-supply = <&pm8994_s4>; + vdd-ntn-phy-supply = <&pm8994_l29>; + vdd-ntn-core-supply = <&pm8994_l31>; qcom,ntn-rst-delay-msec = <100>; qcom,ntn-rc-num = <1>; diff --git a/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi index 6fafb8b38d06..f544934c84e4 100644 --- a/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016,2018, 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 @@ -340,7 +340,6 @@ }; }; -#include "msm8996-sde-display.dtsi" #include "msm8996-mdss-panels.dtsi" &mdss_mdp { @@ -400,7 +399,6 @@ qcom,mdss-dsi-bl-min-level = <1>; qcom,mdss-dsi-bl-max-level = <4095>; qcom,cont-splash-enabled; - qcom,panel-supply-entries = <&dsi_panel_pwr_supply_vdd_no_labibb>; qcom,platform-reset-gpio = <&tlmm 8 0>; qcom,platform-bklight-en-gpio = <&pm8994_gpios 14 0>; qcom,5v-boost-gpio = <&pmi8994_gpios 8 0>; diff --git a/arch/arm/boot/dts/qcom/msm8996-cv2x.dtsi b/arch/arm/boot/dts/qcom/msm8996-cv2x.dtsi index 3223d874cc23..c06a44c31b34 100644 --- a/arch/arm/boot/dts/qcom/msm8996-cv2x.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-cv2x.dtsi @@ -190,12 +190,6 @@ }; }; -/delete-node/ &sde_kms; -/delete-node/ &sde_dsi0; -/delete-node/ &sde_dsi1; -/delete-node/ &sde_dsi_phy0; -/delete-node/ &sde_dsi_phy1; -/delete-node/ &sde_hdmi_tx; /delete-node/ &mdss_mdp; /delete-node/ &mdss_dsi; /delete-node/ &msm_ext_disp; diff --git a/arch/arm/boot/dts/qcom/msm8996-dtp.dtsi b/arch/arm/boot/dts/qcom/msm8996-dtp.dtsi index c2667b49fedb..23709bf5948d 100644 --- a/arch/arm/boot/dts/qcom/msm8996-dtp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-dtp.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016,2018, 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 @@ -11,9 +11,9 @@ */ #include "msm8996-pinctrl.dtsi" -#include "msm8996-sde-display.dtsi" #include "msm8996-camera-sensor-dtp.dtsi" #include "msm8996-wsa881x.dtsi" +#include "msm8996-mdss-panels.dtsi" / { model = "Qualcomm Technologies, Inc. MSM8996 DTP"; diff --git a/arch/arm/boot/dts/qcom/msm8996-fluid.dtsi b/arch/arm/boot/dts/qcom/msm8996-fluid.dtsi index 86bc8099c4d6..de63afeb1b69 100644 --- a/arch/arm/boot/dts/qcom/msm8996-fluid.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-fluid.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016,2018, 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 @@ -587,7 +587,6 @@ status = "ok"; }; -#include "msm8996-sde-display.dtsi" #include "msm8996-mdss-panels.dtsi" &mdss_mdp { diff --git a/arch/arm/boot/dts/qcom/msm8996-liquid.dtsi b/arch/arm/boot/dts/qcom/msm8996-liquid.dtsi index 571e67a7dd93..3eef360c54c2 100644 --- a/arch/arm/boot/dts/qcom/msm8996-liquid.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-liquid.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016,2018, 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 @@ -294,12 +294,16 @@ }; }; -#include "msm8996-sde-display.dtsi" +#include "msm8996-mdss-panels.dtsi" &mdss_mdp { qcom,mdss-pref-prim-intf = "dsi"; }; +&mdss_dsi { + hw-config = "split_dsi"; +}; + &mdss_dsi0 { qcom,dsi-pref-prim-pan = <&dsi_dual_jdi_4k_nofbc_video>; pinctrl-names = "mdss_default", "mdss_sleep"; diff --git a/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi index 24f593aa5e9f..9442239c56a5 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-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, 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 @@ -336,21 +336,12 @@ }; }; -#include "msm8996-sde-display.dtsi" #include "msm8996-mdss-panels.dtsi" &mdss_mdp { qcom,mdss-pref-prim-intf = "dsi"; }; -&sde_hdmi { - status = "ok"; -}; - -&mdss_dsi { - hw-config = "split_dsi"; -}; - &mdss_dsi0 { qcom,dsi-pref-prim-pan = <&dsi_dual_sharp_video>; pinctrl-names = "mdss_default", "mdss_sleep"; @@ -385,7 +376,7 @@ qcom,mdss-dsi-bl-min-level = <1>; qcom,mdss-dsi-bl-max-level = <4095>; qcom,cont-splash-enabled; - qcom,panel-supply-entries = <&dsi_panel_pwr_supply_vdd_no_labibb>; + qcom,panel-supply-entries = <&dsi_panel_pwr_supply_no_labibb>; qcom,platform-reset-gpio = <&tlmm 8 0>; qcom,platform-bklight-en-gpio = <&pm8994_gpios 14 0>; qcom,5v-boost-gpio = <&pmi8994_gpios 8 0>; diff --git a/arch/arm/boot/dts/qcom/msm8996-v2.dtsi b/arch/arm/boot/dts/qcom/msm8996-v2.dtsi index 698c0193a164..db6237072829 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-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, 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,11 +480,7 @@ gdsc-venus-supply = <&gdsc_venus>; }; -&sde_hdmi_tx { - hpd-gdsc-venus-supply = <&gdsc_venus>; -}; - -&mdss_dsi0 { +&mdss_dsi { gdsc-venus-supply = <&gdsc_venus>; qcom,core-supply-entries { #address-cells = <1>; diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi index 2d30aab29a0e..efc91f9f86f7 100644 --- a/arch/arm/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996.dtsi @@ -266,7 +266,6 @@ }; #include "msm8996-ion.dtsi" -#include "msm8996-sde.dtsi" #include "msm8996-mdss.dtsi" #include "msm8996-mdss-pll.dtsi" #include "msm8996-smp2p.dtsi" diff --git a/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-ivi-la.dts b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-ivi-la.dts index e76fcfeb33cc..7900d963bef3 100644 --- a/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-ivi-la.dts +++ b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-ivi-la.dts @@ -255,6 +255,7 @@ qcom,master-en = <1>; /* Enable GPIO */ status = "okay"; }; +}; &sde_kms_hyp { qcom,client-id = "7815"; diff --git a/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-telematics.dts b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-telematics.dts index 83f87d0ee2ff..d063a883a9e1 100644 --- a/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-telematics.dts +++ b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-telematics.dts @@ -183,7 +183,7 @@ subsys_notif_virt: qcom,subsys_notif_virt@2D000000 { compatible = "qcom,subsys-notif-virt"; - reg = <0x2D000000 0x10>; + reg = <0x2D000000 0x18>; reg-names = "vdev_base"; adsp { subsys-name = "adsp"; @@ -193,6 +193,10 @@ subsys-name = "modem"; offset = <8>; }; + wlan { + subsys-name = "AR6320"; + offset = <16>; + }; }; }; diff --git a/arch/arm64/configs/msm-auto-perf_defconfig b/arch/arm64/configs/msm-auto-perf_defconfig index af539a58a0ea..3d7794040c2a 100644 --- a/arch/arm64/configs/msm-auto-perf_defconfig +++ b/arch/arm64/configs/msm-auto-perf_defconfig @@ -232,6 +232,8 @@ CONFIG_MSM_BT_POWER=y CONFIG_BTFM_SLIM=y CONFIG_BTFM_SLIM_WCN3990=y CONFIG_CFG80211=y +CONFIG_CFG80211_CERTIFICATION_ONUS=y +CONFIG_CFG80211_REG_CELLULAR_HINTS=y CONFIG_CFG80211_INTERNAL_REGDB=y CONFIG_RFKILL=y CONFIG_IPC_ROUTER=y @@ -497,6 +499,7 @@ CONFIG_IPA_UT=y CONFIG_GPIO_USB_DETECT=y CONFIG_MSM_MHI=y CONFIG_MSM_MHI_UCI=y +CONFIG_MSM_11AD=y CONFIG_SEEMP_CORE=y CONFIG_USB_BAM=y CONFIG_MSM_MDSS_PLL=y diff --git a/arch/arm64/configs/msm-auto_defconfig b/arch/arm64/configs/msm-auto_defconfig index a01e342f2343..7bbf952a1245 100644 --- a/arch/arm64/configs/msm-auto_defconfig +++ b/arch/arm64/configs/msm-auto_defconfig @@ -234,6 +234,8 @@ CONFIG_MSM_BT_POWER=y CONFIG_BTFM_SLIM=y CONFIG_BTFM_SLIM_WCN3990=y CONFIG_CFG80211=y +CONFIG_CFG80211_CERTIFICATION_ONUS=y +CONFIG_CFG80211_REG_CELLULAR_HINTS=y CONFIG_CFG80211_INTERNAL_REGDB=y CONFIG_RFKILL=y CONFIG_IPC_ROUTER=y @@ -503,6 +505,7 @@ CONFIG_GPIO_USB_DETECT=y CONFIG_MSM_MHI=y CONFIG_MSM_MHI_UCI=y CONFIG_MSM_MHI_DEBUG=y +CONFIG_MSM_11AD=y CONFIG_SEEMP_CORE=y CONFIG_USB_BAM=y CONFIG_MSM_MDSS_PLL=y diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig index 72ef08668808..61e1e347532d 100644 --- a/arch/arm64/configs/msmcortex-perf_defconfig +++ b/arch/arm64/configs/msmcortex-perf_defconfig @@ -232,6 +232,8 @@ CONFIG_MSM_BT_POWER=y CONFIG_BTFM_SLIM=y CONFIG_BTFM_SLIM_WCN3990=y CONFIG_CFG80211=y +CONFIG_CFG80211_CERTIFICATION_ONUS=y +CONFIG_CFG80211_REG_CELLULAR_HINTS=y CONFIG_CFG80211_INTERNAL_REGDB=y CONFIG_RFKILL=y CONFIG_NFC_NQ=y diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig index 039efa9a16e0..48d4f4207735 100644 --- a/arch/arm64/configs/msmcortex_defconfig +++ b/arch/arm64/configs/msmcortex_defconfig @@ -233,6 +233,8 @@ CONFIG_MSM_BT_POWER=y CONFIG_BTFM_SLIM=y CONFIG_BTFM_SLIM_WCN3990=y CONFIG_CFG80211=y +CONFIG_CFG80211_CERTIFICATION_ONUS=y +CONFIG_CFG80211_REG_CELLULAR_HINTS=y CONFIG_CFG80211_INTERNAL_REGDB=y # CONFIG_CFG80211_CRDA_SUPPORT is not set CONFIG_RFKILL=y diff --git a/arch/arm64/configs/msmcortex_mediabox-perf_defconfig b/arch/arm64/configs/msmcortex_mediabox-perf_defconfig index 0feefe5ba25a..2c7be3c7b5d6 100644 --- a/arch/arm64/configs/msmcortex_mediabox-perf_defconfig +++ b/arch/arm64/configs/msmcortex_mediabox-perf_defconfig @@ -232,6 +232,7 @@ CONFIG_BTFM_SLIM=y CONFIG_BTFM_SLIM_WCN3990=y CONFIG_CFG80211=y CONFIG_CFG80211_CERTIFICATION_ONUS=y +CONFIG_CFG80211_REG_CELLULAR_HINTS=y CONFIG_CFG80211_INTERNAL_REGDB=y CONFIG_CFG80211_WEXT=y CONFIG_MAC80211=m diff --git a/arch/arm64/configs/msmcortex_mediabox_defconfig b/arch/arm64/configs/msmcortex_mediabox_defconfig index 8c1bce2e4f12..03e43dc0b7c0 100644 --- a/arch/arm64/configs/msmcortex_mediabox_defconfig +++ b/arch/arm64/configs/msmcortex_mediabox_defconfig @@ -233,6 +233,7 @@ CONFIG_BTFM_SLIM=y CONFIG_BTFM_SLIM_WCN3990=y CONFIG_CFG80211=y CONFIG_CFG80211_CERTIFICATION_ONUS=y +CONFIG_CFG80211_REG_CELLULAR_HINTS=y CONFIG_CFG80211_INTERNAL_REGDB=y # CONFIG_CFG80211_CRDA_SUPPORT is not set CONFIG_CFG80211_WEXT=y diff --git a/arch/arm64/configs/sdm660-perf_defconfig b/arch/arm64/configs/sdm660-perf_defconfig index 81cf6eb30e90..1a832addca83 100644 --- a/arch/arm64/configs/sdm660-perf_defconfig +++ b/arch/arm64/configs/sdm660-perf_defconfig @@ -232,6 +232,8 @@ CONFIG_MSM_BT_POWER=y CONFIG_BTFM_SLIM=y CONFIG_BTFM_SLIM_WCN3990=y CONFIG_CFG80211=y +CONFIG_CFG80211_CERTIFICATION_ONUS=y +CONFIG_CFG80211_REG_CELLULAR_HINTS=y CONFIG_CFG80211_INTERNAL_REGDB=y CONFIG_RFKILL=y CONFIG_NFC_NQ=y diff --git a/arch/arm64/configs/sdm660_defconfig b/arch/arm64/configs/sdm660_defconfig index bd7ec3ab3a94..85175deb6efa 100644 --- a/arch/arm64/configs/sdm660_defconfig +++ b/arch/arm64/configs/sdm660_defconfig @@ -233,6 +233,8 @@ CONFIG_MSM_BT_POWER=y CONFIG_BTFM_SLIM=y CONFIG_BTFM_SLIM_WCN3990=y CONFIG_CFG80211=y +CONFIG_CFG80211_CERTIFICATION_ONUS=y +CONFIG_CFG80211_REG_CELLULAR_HINTS=y CONFIG_CFG80211_INTERNAL_REGDB=y # CONFIG_CFG80211_CRDA_SUPPORT is not set CONFIG_RFKILL=y diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c index 16ff781cde65..b0b36d00415d 100644 --- a/drivers/char/diag/diag_dci.c +++ b/drivers/char/diag/diag_dci.c @@ -689,7 +689,7 @@ int diag_dci_query_log_mask(struct diag_dci_client_tbl *entry, byte_mask = 0x01 << (item_num % 8); offset = equip_id * 514; - if (offset + byte_index > DCI_LOG_MASK_SIZE) { + if (offset + byte_index >= DCI_LOG_MASK_SIZE) { pr_err("diag: In %s, invalid offset: %d, log_code: %d, byte_index: %d\n", __func__, offset, log_code, byte_index); return 0; @@ -716,7 +716,7 @@ int diag_dci_query_event_mask(struct diag_dci_client_tbl *entry, bit_index = event_id % 8; byte_mask = 0x1 << bit_index; - if (byte_index > DCI_EVENT_MASK_SIZE) { + if (byte_index >= DCI_EVENT_MASK_SIZE) { pr_err("diag: In %s, invalid, event_id: %d, byte_index: %d\n", __func__, event_id, byte_index); return 0; diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index ff0c8327fabe..3c3cf8e04eea 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 2016-2018, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -210,9 +210,11 @@ static unsigned long clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_rcg2 *rcg = to_clk_rcg2(hw); + const struct freq_tbl *f_curr; u32 cfg, hid_div, m = 0, n = 0, mode = 0, mask; - if (rcg->enable_safe_config && !clk_hw_is_prepared(hw)) { + if (rcg->enable_safe_config && (!clk_hw_is_prepared(hw) + || !clk_hw_is_enabled(hw))) { if (!rcg->current_freq) rcg->current_freq = cxo_f.freq; return rcg->current_freq; @@ -232,9 +234,17 @@ clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) mode >>= CFG_MODE_SHIFT; } - mask = BIT(rcg->hid_width) - 1; - hid_div = cfg >> CFG_SRC_DIV_SHIFT; - hid_div &= mask; + if (rcg->enable_safe_config) { + f_curr = qcom_find_freq(rcg->freq_tbl, rcg->current_freq); + if (!f_curr) + return -EINVAL; + + hid_div = f_curr->pre_div; + } else { + mask = BIT(rcg->hid_width) - 1; + hid_div = cfg >> CFG_SRC_DIV_SHIFT; + hid_div &= mask; + } return calc_rate(parent_rate, m, n, mode, hid_div); } diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c index 584a1857624a..324cce5d7354 100644 --- a/drivers/cpuidle/lpm-levels.c +++ b/drivers/cpuidle/lpm-levels.c @@ -1706,7 +1706,8 @@ static int cluster_cpuidle_register(struct lpm_cluster *cl) struct cpuidle_state *st = &cl->drv->states[i]; struct lpm_cpu_level *cpu_level = &cl->cpu->levels[i]; snprintf(st->name, CPUIDLE_NAME_LEN, "C%u\n", i); - snprintf(st->desc, CPUIDLE_DESC_LEN, cpu_level->name); + snprintf(st->desc, CPUIDLE_DESC_LEN, "%s", + cpu_level->name); st->flags = 0; st->exit_latency = cpu_level->pwr.latency_us; st->power_usage = cpu_level->pwr.ss_power; diff --git a/drivers/esoc/esoc-mdm-4x.c b/drivers/esoc/esoc-mdm-4x.c index d071e89d3124..99fd598b5069 100644 --- a/drivers/esoc/esoc-mdm-4x.c +++ b/drivers/esoc/esoc-mdm-4x.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2015, 2017-2018, 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 @@ -230,10 +230,15 @@ static int mdm_cmd_exe(enum esoc_cmd cmd, struct esoc_clink *esoc) } msleep(100); } - if (status_down) + if (status_down) { dev_dbg(dev, "shutdown successful\n"); - else + esoc_clink_queue_request(ESOC_REQ_SHUTDOWN, esoc); + } else { dev_err(mdm->dev, "graceful poff ipc fail\n"); + graceful_shutdown = false; + goto force_poff; + } + break; force_poff: case ESOC_FORCE_PWR_OFF: if (!graceful_shutdown) { diff --git a/drivers/esoc/esoc-mdm-pon.c b/drivers/esoc/esoc-mdm-pon.c index 4be66a16a3a1..0288082cea00 100644 --- a/drivers/esoc/esoc-mdm-pon.c +++ b/drivers/esoc/esoc-mdm-pon.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2015, 2017-2018, 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 @@ -55,7 +55,7 @@ static int mdm9x55_toggle_soft_reset(struct mdm_ctrl *mdm, bool atomic) if (!atomic) usleep_range(reset_time_us, reset_time_us + 100000); else - mdelay(mdm->reset_time_ms); + mdelay(DEF_MDM9X55_RESET_TIME); gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET), soft_reset_direction_de_assert); return 0; diff --git a/drivers/gpu/drm/msm/dba_bridge.c b/drivers/gpu/drm/msm/dba_bridge.c index 9144dfdf30c9..7887bda23df0 100644 --- a/drivers/gpu/drm/msm/dba_bridge.c +++ b/drivers/gpu/drm/msm/dba_bridge.c @@ -51,6 +51,7 @@ struct dba_bridge { u32 num_of_input_lanes; bool pluggable; u32 panel_count; + bool cont_splash_enabled; }; #define to_dba_bridge(x) container_of((x), struct dba_bridge, base) @@ -324,6 +325,7 @@ struct drm_bridge *dba_bridge_init(struct drm_device *dev, bridge->panel_count = data->panel_count; bridge->base.funcs = &_dba_bridge_ops; bridge->base.encoder = encoder; + bridge->cont_splash_enabled = data->cont_splash_enabled; rc = drm_bridge_attach(dev, &bridge->base); if (rc) { @@ -339,7 +341,10 @@ struct drm_bridge *dba_bridge_init(struct drm_device *dev, encoder->bridge = &bridge->base; } - if (!bridge->pluggable) { + /* If early splash has enabled bridge chip in bootloader, + * below call should be skipped. + */ + if (!bridge->pluggable && !bridge->cont_splash_enabled) { if (bridge->ops.power_on) bridge->ops.power_on(bridge->dba_ctx, true, 0); if (bridge->ops.check_hpd) diff --git a/drivers/gpu/drm/msm/dba_bridge.h b/drivers/gpu/drm/msm/dba_bridge.h index 5562d2b2aef9..edc130f92257 100644 --- a/drivers/gpu/drm/msm/dba_bridge.h +++ b/drivers/gpu/drm/msm/dba_bridge.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018, 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 @@ -44,6 +44,7 @@ struct dba_bridge_init { struct drm_bridge *precede_bridge; bool pluggable; u32 panel_count; + bool cont_splash_enabled; }; /** diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c index 6015cf35e030..7a90c7be4e5c 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c @@ -1598,7 +1598,7 @@ exit: * * Return: error code. */ -int dsi_ctrl_host_init(struct dsi_ctrl *dsi_ctrl) +int dsi_ctrl_host_init(struct dsi_ctrl *dsi_ctrl, bool cont_splash_enabled) { int rc = 0; @@ -1615,37 +1615,40 @@ int dsi_ctrl_host_init(struct dsi_ctrl *dsi_ctrl) goto error; } - dsi_ctrl->hw.ops.setup_lane_map(&dsi_ctrl->hw, + if (!cont_splash_enabled) { + dsi_ctrl->hw.ops.setup_lane_map(&dsi_ctrl->hw, &dsi_ctrl->host_config.lane_map); - dsi_ctrl->hw.ops.host_setup(&dsi_ctrl->hw, + dsi_ctrl->hw.ops.host_setup(&dsi_ctrl->hw, &dsi_ctrl->host_config.common_config); - if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) { - dsi_ctrl->hw.ops.cmd_engine_setup(&dsi_ctrl->hw, + if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) { + dsi_ctrl->hw.ops.cmd_engine_setup(&dsi_ctrl->hw, &dsi_ctrl->host_config.common_config, &dsi_ctrl->host_config.u.cmd_engine); - dsi_ctrl->hw.ops.setup_cmd_stream(&dsi_ctrl->hw, + dsi_ctrl->hw.ops.setup_cmd_stream(&dsi_ctrl->hw, dsi_ctrl->host_config.video_timing.h_active, dsi_ctrl->host_config.video_timing.h_active * 3, dsi_ctrl->host_config.video_timing.v_active, 0x0); - } else { - dsi_ctrl->hw.ops.video_engine_setup(&dsi_ctrl->hw, + } else { + dsi_ctrl->hw.ops.video_engine_setup(&dsi_ctrl->hw, &dsi_ctrl->host_config.common_config, &dsi_ctrl->host_config.u.video_engine); - dsi_ctrl->hw.ops.set_video_timing(&dsi_ctrl->hw, + dsi_ctrl->hw.ops.set_video_timing(&dsi_ctrl->hw, &dsi_ctrl->host_config.video_timing); + } } - - dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0); dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0x0); - /* Perform a soft reset before enabling dsi controller */ - dsi_ctrl->hw.ops.soft_reset(&dsi_ctrl->hw); + /* Perform a soft reset before enabling dsi controller + * But skip the reset if dsi is enabled in bootloader. + */ + if (!cont_splash_enabled) + dsi_ctrl->hw.ops.soft_reset(&dsi_ctrl->hw); pr_debug("[DSI_%d]Host initialization complete\n", dsi_ctrl->index); dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, 0x1); error: @@ -1967,6 +1970,12 @@ error: return rc; } +void dsi_ctrl_update_power_state(struct dsi_ctrl *dsi_ctrl, + enum dsi_power_state state) +{ + dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_POWER_STATE_CHANGE, state); +} + /** * dsi_ctrl_set_tpg_state() - enable/disable test pattern on the controller * @dsi_ctrl: DSI controller handle. diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h index 993a35cbf84a..c0ba532011b5 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2016, 2018 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 @@ -331,6 +331,7 @@ int dsi_ctrl_phy_sw_reset(struct dsi_ctrl *dsi_ctrl); /** * dsi_ctrl_host_init() - Initialize DSI host hardware. * @dsi_ctrl: DSI controller handle. + * @cont_splash_enabled: Flag for DSI splash enabled in bootloader. * * Initializes DSI controller hardware with host configuration provided by * dsi_ctrl_update_host_config(). Initialization can be performed only during @@ -339,7 +340,7 @@ int dsi_ctrl_phy_sw_reset(struct dsi_ctrl *dsi_ctrl); * * Return: error code. */ -int dsi_ctrl_host_init(struct dsi_ctrl *dsi_ctrl); +int dsi_ctrl_host_init(struct dsi_ctrl *dsi_ctrl, bool cont_splash_enabled); /** * dsi_ctrl_host_deinit() - De-Initialize DSI host hardware. @@ -404,6 +405,16 @@ int dsi_ctrl_set_power_state(struct dsi_ctrl *dsi_ctrl, enum dsi_power_state state); /** + * dsi_ctrl_update_power_state() - update power state for dsi controller + * @dsi_ctrl: DSI controller handle. + * @state: Power state. + * + * Update power state for DSI controller. + * + */ +void dsi_ctrl_update_power_state(struct dsi_ctrl *dsi_ctrl, + enum dsi_power_state state); +/** * dsi_ctrl_set_cmd_engine_state() - set command engine state * @dsi_ctrl: DSI Controller handle. * @state: Engine state. diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index 09ab14cc4746..c468a6f5caa2 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -174,6 +174,11 @@ static int dsi_display_ctrl_power_on(struct dsi_display *display) int i; struct dsi_display_ctrl *ctrl; + if (display->cont_splash_enabled) { + pr_debug("skip ctrl power on\n"); + return rc; + } + /* Sequence does not matter for split dsi usecases */ for (i = 0; i < display->ctrl_count; i++) { @@ -460,7 +465,8 @@ static int dsi_display_ctrl_init(struct dsi_display *display) for (i = 0 ; i < display->ctrl_count; i++) { ctrl = &display->ctrl[i]; - rc = dsi_ctrl_host_init(ctrl->ctrl); + rc = dsi_ctrl_host_init(ctrl->ctrl, + display->cont_splash_enabled); if (rc) { pr_err("[%s] failed to init host_%d, rc=%d\n", display->name, i, rc); @@ -720,7 +726,7 @@ static int dsi_display_phy_enable(struct dsi_display *display) rc = dsi_phy_enable(m_ctrl->phy, &display->config, m_src, - true); + true, display->cont_splash_enabled); if (rc) { pr_err("[%s] failed to enable DSI PHY, rc=%d\n", display->name, rc); @@ -735,7 +741,7 @@ static int dsi_display_phy_enable(struct dsi_display *display) rc = dsi_phy_enable(ctrl->phy, &display->config, DSI_PLL_SOURCE_NON_NATIVE, - true); + true, display->cont_splash_enabled); if (rc) { pr_err("[%s] failed to enable DSI PHY, rc=%d\n", display->name, rc); @@ -848,6 +854,11 @@ static int dsi_display_phy_sw_reset(struct dsi_display *display) int i; struct dsi_display_ctrl *m_ctrl, *ctrl; + if (display->cont_splash_enabled) { + pr_debug("skip phy sw reset\n"); + return 0; + } + m_ctrl = &display->ctrl[display->cmd_master_idx]; rc = dsi_ctrl_phy_sw_reset(m_ctrl->ctrl); @@ -1748,6 +1759,45 @@ static int _dsi_display_dev_deinit(struct dsi_display *display) return rc; } +/* + * _dsi_display_config_ctrl_for_splash + * + * Config ctrl engine for DSI display. + * @display: Handle to the display + * Returns: Zero on success + */ +static int _dsi_display_config_ctrl_for_splash(struct dsi_display *display) +{ + int rc = 0; + + if (!display) { + pr_err("Invalid params\n"); + return -EINVAL; + } + + if (display->config.panel_mode == DSI_OP_VIDEO_MODE) { + rc = dsi_display_vid_engine_enable(display); + if (rc) { + pr_err("[%s]failed to enable video engine, rc=%d\n", + display->name, rc); + goto error_out; + } + } else if (display->config.panel_mode == DSI_OP_CMD_MODE) { + rc = dsi_display_cmd_engine_enable(display); + if (rc) { + pr_err("[%s]failed to enable cmd engine, rc=%d\n", + display->name, rc); + goto error_out; + } + } else { + pr_err("[%s] Invalid configuration\n", display->name); + rc = -EINVAL; + } + +error_out: + return rc; +} + /** * dsi_display_bind - bind dsi device with controlling device * @dev: Pointer to base of platform device @@ -2141,6 +2191,8 @@ int dsi_display_drm_bridge_init(struct dsi_display *display, init_data.num_of_input_lanes = num_of_lanes; init_data.precede_bridge = precede_bridge; init_data.panel_count = display->panel_count; + init_data.cont_splash_enabled = + display->cont_splash_enabled; dba_bridge = dba_bridge_init(display->drm_dev, enc, &init_data); if (IS_ERR_OR_NULL(dba_bridge)) { @@ -2451,26 +2503,28 @@ int dsi_display_prepare(struct dsi_display *display) mutex_lock(&display->display_lock); - for (i = 0; i < display->panel_count; i++) { - rc = dsi_panel_pre_prepare(display->panel[i]); - if (rc) { - SDE_ERROR("[%s] panel pre-prepare failed, rc=%d\n", - display->name, rc); - goto error_panel_post_unprep; + if (!display->cont_splash_enabled) { + for (i = 0; i < display->panel_count; i++) { + rc = dsi_panel_pre_prepare(display->panel[i]); + if (rc) { + SDE_ERROR("[%s]pre-prepare failed, rc=%d\n", + display->name, rc); + goto error_panel_post_unprep; + } } } rc = dsi_display_ctrl_power_on(display); if (rc) { pr_err("[%s] failed to power on dsi controllers, rc=%d\n", - display->name, rc); + display->name, rc); goto error_panel_post_unprep; } rc = dsi_display_phy_power_on(display); if (rc) { pr_err("[%s] failed to power on dsi phy, rc = %d\n", - display->name, rc); + display->name, rc); goto error_ctrl_pwr_off; } @@ -2497,21 +2551,21 @@ int dsi_display_prepare(struct dsi_display *display) rc = dsi_display_ctrl_init(display); if (rc) { pr_err("[%s] failed to setup DSI controller, rc=%d\n", - display->name, rc); + display->name, rc); goto error_phy_disable; } rc = dsi_display_ctrl_link_clk_on(display); if (rc) { pr_err("[%s] failed to enable DSI link clocks, rc=%d\n", - display->name, rc); + display->name, rc); goto error_ctrl_deinit; } rc = dsi_display_ctrl_host_enable(display); if (rc) { pr_err("[%s] failed to enable DSI host, rc=%d\n", - display->name, rc); + display->name, rc); goto error_ctrl_link_off; } @@ -2519,11 +2573,10 @@ int dsi_display_prepare(struct dsi_display *display) rc = dsi_panel_prepare(display->panel[j]); if (rc) { SDE_ERROR("[%s] panel prepare failed, rc=%d\n", - display->name, rc); + display->name, rc); goto error_panel_unprep; } } - goto error; error_panel_unprep: @@ -2559,6 +2612,12 @@ int dsi_display_enable(struct dsi_display *display) return -EINVAL; } + if (display->cont_splash_enabled) { + _dsi_display_config_ctrl_for_splash(display); + display->cont_splash_enabled = false; + return 0; + } + mutex_lock(&display->display_lock); for (i = 0; i < display->panel_count; i++) { @@ -2755,6 +2814,46 @@ int dsi_display_unprepare(struct dsi_display *display) return rc; } +int dsi_dsiplay_setup_splash_resource(struct dsi_display *display) +{ + int ret = 0, i = 0; + struct dsi_display_ctrl *ctrl; + + if (!display) + return -EINVAL; + + for (i = 0; i < display->ctrl_count; i++) { + ctrl = &display->ctrl[i]; + if (!ctrl) + return -EINVAL; + + dsi_pwr_enable_regulator(&ctrl->ctrl->pwr_info.host_pwr, true); + dsi_pwr_enable_regulator(&ctrl->ctrl->pwr_info.digital, true); + dsi_pwr_enable_regulator(&ctrl->phy->pwr_info.phy_pwr, true); + + ret = dsi_clk_enable_core_clks(&ctrl->ctrl->clk_info.core_clks, + true); + if (ret) { + SDE_ERROR("failed to set core clk for dsi, ret = %d\n", + ret); + return -EINVAL; + } + + ret = dsi_clk_enable_link_clks(&ctrl->ctrl->clk_info.link_clks, + true); + if (ret) { + SDE_ERROR("failed to set link clk for dsi, ret = %d\n", + ret); + return -EINVAL; + } + + dsi_ctrl_update_power_state(ctrl->ctrl, + DSI_CTRL_POWER_LINK_CLK_ON); + } + + return ret; +} + static int __init dsi_display_register(void) { dsi_phy_drv_register(); diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h index 210b8d00850b..3723f19fd0e7 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2018, 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 @@ -158,6 +158,8 @@ struct dsi_display { /* DEBUG FS */ struct dentry *root; + + bool cont_splash_enabled; }; int dsi_display_dev_probe(struct platform_device *pdev); @@ -338,4 +340,15 @@ int dsi_display_clock_gate(struct dsi_display *display, bool enable); int dsi_dispaly_static_frame(struct dsi_display *display, bool enable); int dsi_display_set_backlight(void *display, u32 bl_lvl); + +/** + * dsi_dsiplay_setup_splash_resource + * @display: Handle to display. + * + * Setup DSI splash resource to avoid reset and glitch if DSI is enabled + * in bootloder. + * + * Return: error code. + */ +int dsi_dsiplay_setup_splash_resource(struct dsi_display *display); #endif /* _DSI_DISPLAY_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c index 1ccbbe7df573..da3b3b548e5f 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2016, 2018 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 @@ -721,9 +721,10 @@ error: * Return: error code. */ int dsi_phy_enable(struct msm_dsi_phy *phy, - struct dsi_host_config *config, - enum dsi_phy_pll_source pll_source, - bool skip_validation) + struct dsi_host_config *config, + enum dsi_phy_pll_source pll_source, + bool skip_validation, + bool cont_splash_enabled) { int rc = 0; @@ -758,7 +759,8 @@ int dsi_phy_enable(struct msm_dsi_phy *phy, goto error_disable_clks; } - dsi_phy_enable_hw(phy); + if (!cont_splash_enabled) + dsi_phy_enable_hw(phy); error_disable_clks: rc = dsi_clk_enable_core_clks(&phy->clks.core_clks, false); diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h index 6c31bfa3ea00..aa21d0b347e8 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2016, 2018 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 @@ -157,9 +157,10 @@ int dsi_phy_set_power_state(struct msm_dsi_phy *dsi_phy, bool enable); * Return: error code. */ int dsi_phy_enable(struct msm_dsi_phy *dsi_phy, - struct dsi_host_config *config, - enum dsi_phy_pll_source pll_source, - bool skip_validation); + struct dsi_host_config *config, + enum dsi_phy_pll_source pll_source, + bool skip_validation, + bool cont_splash_enabled); /** * dsi_phy_disable() - disable DSI PHY hardware. diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c index 21b89663a9c3..852ac80410f0 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c @@ -1311,7 +1311,7 @@ static int _sde_hdmi_hpd_enable(struct sde_hdmi *sde_hdmi) } } - if (!sde_kms->splash_info.handoff) { + if (!sde_hdmi->cont_splash_enabled) { sde_hdmi_set_mode(hdmi, false); _sde_hdmi_phy_reset(hdmi); sde_hdmi_set_mode(hdmi, true); @@ -3186,7 +3186,6 @@ int sde_hdmi_drm_init(struct sde_hdmi *display, struct drm_encoder *enc) struct msm_drm_private *priv = NULL; struct hdmi *hdmi; struct platform_device *pdev; - struct sde_kms *sde_kms; DBG(""); if (!display || !display->drm_dev || !enc) { @@ -3252,8 +3251,7 @@ int sde_hdmi_drm_init(struct sde_hdmi *display, struct drm_encoder *enc) * clocks. This can skip the clock disabling operation in * clock_late_init when finding clk.count == 1. */ - sde_kms = to_sde_kms(priv->kms); - if (sde_kms->splash_info.handoff) { + if (display->cont_splash_enabled) { sde_hdmi_bridge_power_on(hdmi->bridge); hdmi->power_on = true; } else { diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h index 607d2cf3c7b7..9cf807e829c7 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h @@ -196,6 +196,8 @@ struct sde_hdmi { struct dss_io_data io[HDMI_TX_MAX_IO]; /* DEBUG FS */ struct dentry *root; + + bool cont_splash_enabled; }; /** diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index ea3f138ee461..cd00ab4b4a81 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -39,10 +39,10 @@ #include "sde_trace.h" /* default input fence timeout, in ms */ -#define SDE_CRTC_INPUT_FENCE_TIMEOUT 2000 +#define SDE_CRTC_INPUT_FENCE_TIMEOUT 10000 /* - * The default input fence timeout is 2 seconds while max allowed + * The default input fence timeout is 10 seconds while max allowed * range is 10 seconds. Any value above 10 seconds adds glitches beyond * tolerance limit. */ @@ -1625,8 +1625,18 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc, sde_kms_info_add_keyint(info, "hw_version", catalog->hwversion); sde_kms_info_add_keyint(info, "max_linewidth", catalog->max_mixer_width); - sde_kms_info_add_keyint(info, "max_blendstages", - catalog->max_mixer_blendstages); + + /* till now, we can't know which display early RVC will run on. + * Not to impact early RVC's layer, we decrease all lm's blend stage. + * This should be restored after handoff is done. + */ + if (sde_kms->splash_info.handoff) + sde_kms_info_add_keyint(info, "max_blendstages", + catalog->max_mixer_blendstages - 1); + else + sde_kms_info_add_keyint(info, "max_blendstages", + catalog->max_mixer_blendstages); + if (catalog->qseed_type == SDE_SSPP_SCALER_QSEED2) sde_kms_info_add_keystr(info, "qseed_type", "qseed2"); if (catalog->qseed_type == SDE_SSPP_SCALER_QSEED3) diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index a94de553c855..b95157b28855 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -639,6 +639,15 @@ static int _sde_kms_setup_displays(struct drm_device *dev, continue; } + rc = sde_splash_setup_display_resource(&sde_kms->splash_info, + display, DRM_MODE_CONNECTOR_DSI); + if (rc) { + SDE_ERROR("dsi %d splash resource setup failed %d\n", + i, rc); + sde_encoder_destroy(encoder); + continue; + } + rc = dsi_display_drm_bridge_init(display, encoder); if (rc) { SDE_ERROR("dsi bridge %d init failed, %d\n", i, rc); @@ -731,6 +740,15 @@ static int _sde_kms_setup_displays(struct drm_device *dev, continue; } + rc = sde_splash_setup_display_resource(&sde_kms->splash_info, + display, DRM_MODE_CONNECTOR_HDMIA); + if (rc) { + SDE_ERROR("hdmi %d splash resource setup failed %d\n", + i, rc); + sde_encoder_destroy(encoder); + continue; + } + rc = sde_hdmi_drm_init(display, encoder); if (rc) { SDE_ERROR("hdmi drm %d init failed, %d\n", i, rc); @@ -812,6 +830,7 @@ static int _sde_kms_drm_obj_init(struct sde_kms *sde_kms) struct msm_drm_private *priv; struct sde_mdss_cfg *catalog; + struct sde_splash_info *sinfo; int primary_planes_idx, i, ret; int max_crtc_count, max_plane_count; @@ -824,6 +843,7 @@ static int _sde_kms_drm_obj_init(struct sde_kms *sde_kms) dev = sde_kms->dev; priv = dev->dev_private; catalog = sde_kms->catalog; + sinfo = &sde_kms->splash_info; ret = sde_core_irq_domain_add(sde_kms); if (ret) @@ -851,7 +871,7 @@ static int _sde_kms_drm_obj_init(struct sde_kms *sde_kms) primary = false; plane = sde_plane_init(dev, catalog->vp[i].id, - primary, 1UL << crtc_id, true); + primary, 1UL << crtc_id, true, false); if (IS_ERR(plane)) { SDE_ERROR("sde_plane_init failed\n"); ret = PTR_ERR(plane); @@ -869,14 +889,22 @@ static int _sde_kms_drm_obj_init(struct sde_kms *sde_kms) for (i = 0; i < max_plane_count; i++) { bool primary = true; + bool resv_plane = false; if (catalog->sspp[i].features & BIT(SDE_SSPP_CURSOR) || primary_planes_idx >= max_crtc_count) primary = false; + if (sde_splash_query_plane_is_reserved(sinfo, + catalog->sspp[i].id)) { + resv_plane = true; + DRM_INFO("pipe%d is reserved\n", + catalog->sspp[i].id); + } + plane = sde_plane_init(dev, catalog->sspp[i].id, primary, (1UL << max_crtc_count) - 1, - false); + false, resv_plane); if (IS_ERR(plane)) { SDE_ERROR("sde_plane_init failed\n"); ret = PTR_ERR(plane); @@ -1337,12 +1365,17 @@ static int sde_kms_hw_init(struct msm_kms *kms) */ sinfo = &sde_kms->splash_info; if (sinfo->handoff) { - rc = sde_splash_parse_dt(dev); + rc = sde_splash_parse_memory_dt(dev); if (rc) { - SDE_ERROR("parse dt for splash info failed: %d\n", rc); + SDE_ERROR("parse memory dt failed: %d\n", rc); goto power_error; } + rc = sde_splash_parse_reserved_plane_dt(sinfo, + sde_kms->catalog); + if (rc) + SDE_ERROR("parse reserved plane dt failed: %d\n", rc); + sde_splash_init(&priv->phandle, kms); } diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c index acd5687f6d11..ceac5a931e7e 100644 --- a/drivers/gpu/drm/msm/sde/sde_plane.c +++ b/drivers/gpu/drm/msm/sde/sde_plane.c @@ -1798,7 +1798,7 @@ static void sde_plane_atomic_update(struct drm_plane *plane, /* helper to install properties which are common to planes and crtcs */ static void _sde_plane_install_properties(struct drm_plane *plane, - struct sde_mdss_cfg *catalog) + struct sde_mdss_cfg *catalog, bool plane_reserved) { static const struct drm_prop_enum_list e_blend_op[] = { {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"}, @@ -1994,6 +1994,16 @@ static void _sde_plane_install_properties(struct drm_plane *plane, sde_kms_info_add_keyint(info, "max_downscale", maxdwnscale); sde_kms_info_add_keyint(info, "max_horizontal_deci", maxhdeciexp); sde_kms_info_add_keyint(info, "max_vertical_deci", maxvdeciexp); + + /* When early RVC is enabled in bootloader and doesn't exit, + * user app should not touch the pipe which RVC is on. + * So mark the plane_unavailibility to the special pipe's property, + * user can parse this property of this pipe and stop this pipe's + * allocation after parsing. + * plane_reserved is 1, means the pipe is occupied in bootloader. + * plane_reserved is 0, means it's not used in bootloader. + */ + sde_kms_info_add_keyint(info, "plane_unavailability", plane_reserved); msm_property_set_blob(&psde->property_info, &psde->blob_info, info->data, info->len, PLANE_PROP_INFO); @@ -2731,7 +2741,8 @@ end: /* initialize plane */ struct drm_plane *sde_plane_init(struct drm_device *dev, uint32_t pipe, bool primary_plane, - unsigned long possible_crtcs, bool vp_enabled) + unsigned long possible_crtcs, + bool vp_enabled, bool plane_reserved) { struct drm_plane *plane = NULL; struct sde_plane *psde; @@ -2856,7 +2867,7 @@ struct drm_plane *sde_plane_init(struct drm_device *dev, PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT, sizeof(struct sde_plane_state)); - _sde_plane_install_properties(plane, kms->catalog); + _sde_plane_install_properties(plane, kms->catalog, plane_reserved); /* save user friendly pipe name for later */ snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id); diff --git a/drivers/gpu/drm/msm/sde/sde_plane.h b/drivers/gpu/drm/msm/sde/sde_plane.h index 7b91822d4cde..8ac582643926 100644 --- a/drivers/gpu/drm/msm/sde/sde_plane.h +++ b/drivers/gpu/drm/msm/sde/sde_plane.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark <robdclark@gmail.com> * @@ -77,10 +77,12 @@ void sde_plane_flush(struct drm_plane *plane); * @primary_plane: true if this pipe is primary plane for crtc * @possible_crtcs: bitmask of crtc that can be attached to the given pipe * @vp_enabled: Flag indicating if virtual planes enabled + * @plane_reserved: Flag indicating the plane is occupied in bootloader */ struct drm_plane *sde_plane_init(struct drm_device *dev, uint32_t pipe, bool primary_plane, - unsigned long possible_crtcs, bool vp_enabled); + unsigned long possible_crtcs, + bool vp_enabled, bool plane_reserved); /** * sde_plane_wait_input_fence - wait for input fence object diff --git a/drivers/gpu/drm/msm/sde/sde_splash.c b/drivers/gpu/drm/msm/sde/sde_splash.c index 2789ae053663..f6bd7b040dcb 100644 --- a/drivers/gpu/drm/msm/sde/sde_splash.c +++ b/drivers/gpu/drm/msm/sde/sde_splash.c @@ -23,6 +23,7 @@ #include "sde_hw_intf.h" #include "sde_hw_catalog.h" #include "dsi_display.h" +#include "sde_hdmi.h" #define MDP_SSPP_TOP0_OFF 0x1000 #define DISP_INTF_SEL 0x004 @@ -39,6 +40,10 @@ #define SDE_LK_EXIT_MAX_LOOP 20 +#define INTF_HDMI_SEL (BIT(25) | BIT(24)) +#define INTF_DSI0_SEL BIT(8) +#define INTF_DSI1_SEL BIT(16) + static DEFINE_MUTEX(sde_splash_lock); /* @@ -283,6 +288,44 @@ static void _sde_splash_destroy_splash_node(struct sde_splash_info *sinfo) sinfo->splash_mem_size = NULL; } +static void _sde_splash_sent_pipe_update_uevent(struct sde_kms *sde_kms) +{ + char *event_string; + char *envp[2]; + struct drm_device *dev; + struct device *kdev; + int i = 0; + + if (!sde_kms || !sde_kms->dev) { + DRM_ERROR("invalid input\n"); + return; + } + + dev = sde_kms->dev; + kdev = dev->primary->kdev; + + event_string = kzalloc(SZ_4K, GFP_KERNEL); + if (!event_string) { + SDE_ERROR("failed to allocate event string\n"); + return; + } + + for (i = 0; i < MAX_BLOCKS; i++) { + if (sde_kms->splash_info.reserved_pipe_info[i] != 0xFFFFFFFF) + snprintf(event_string, SZ_4K, "pipe%d avialable", + sde_kms->splash_info.reserved_pipe_info[i]); + } + + DRM_INFO("generating pipe update event[%s]", event_string); + + envp[0] = event_string; + envp[1] = NULL; + + kobject_uevent_env(&kdev->kobj, KOBJ_CHANGE, envp); + + kfree(event_string); +} + static void _sde_splash_get_connector_ref_cnt(struct sde_splash_info *sinfo, u32 *hdmi_cnt, u32 *dsi_cnt) { @@ -372,12 +415,12 @@ void sde_splash_destroy(struct sde_splash_info *sinfo, } /* - * sde_splash_parse_dt. + * sde_splash_parse_memory_dt. * In the function, it will parse and reserve two kinds of memory node. * First is to get the reserved memory for display buffers. - * Second is to get the memory node LK's code stack is running on. + * Second is to get the memory node which LK's heap memory is running on. */ -int sde_splash_parse_dt(struct drm_device *dev) +int sde_splash_parse_memory_dt(struct drm_device *dev) { struct msm_drm_private *priv = dev->dev_private; struct sde_kms *sde_kms; @@ -404,6 +447,79 @@ int sde_splash_parse_dt(struct drm_device *dev) return 0; } +static inline u32 _sde_splash_parse_sspp_id(struct sde_mdss_cfg *cfg, + const char *name) +{ + int i; + + for (i = 0; i < cfg->sspp_count; i++) { + if (!strcmp(cfg->sspp[i].name, name)) + return cfg->sspp[i].id; + } + + return 0; +} + +int sde_splash_parse_reserved_plane_dt(struct sde_splash_info *splash_info, + struct sde_mdss_cfg *cfg) +{ + struct device_node *parent, *node; + struct property *prop; + const char *cname; + int ret = 0, i = 0; + + if (!splash_info || !cfg) + return -EINVAL; + + parent = of_find_node_by_path("/qcom,sde-reserved-plane"); + if (!parent) + return -EINVAL; + + for (i = 0; i < MAX_BLOCKS; i++) + splash_info->reserved_pipe_info[i] = 0xFFFFFFFF; + + i = 0; + for_each_child_of_node(parent, node) { + if (i >= MAX_BLOCKS) { + SDE_ERROR("num of nodes(%d) is bigger than max(%d)\n", + i, MAX_BLOCKS); + ret = -EINVAL; + goto parent_node_err; + } + + of_property_for_each_string(node, "qcom,plane-name", + prop, cname) + splash_info->reserved_pipe_info[i] = + _sde_splash_parse_sspp_id(cfg, cname); + i++; + } + +parent_node_err: + of_node_put(parent); + + return ret; +} + +bool sde_splash_query_plane_is_reserved(struct sde_splash_info *sinfo, + uint32_t pipe) +{ + int i = 0; + + if (!sinfo) + return false; + + /* early return if no splash is enabled */ + if (!sinfo->handoff) + return false; + + for (i = 0; i < MAX_BLOCKS; i++) { + if (sinfo->reserved_pipe_info[i] == pipe) + return true; + } + + return false; +} + int sde_splash_get_handoff_status(struct msm_kms *kms) { uint32_t intf_sel = 0; @@ -448,14 +564,17 @@ int sde_splash_get_handoff_status(struct msm_kms *kms) * considered as single display. So decrement * 'num_of_display_on' by 1 */ - if (split_display) + if (split_display) { num_of_display_on--; + sinfo->split_is_enabled = true; + } } if (num_of_display_on) { sinfo->handoff = true; sinfo->program_scratch_regs = true; sinfo->lk_is_exited = false; + sinfo->intf_sel_status = intf_sel; } else { sinfo->handoff = false; sinfo->program_scratch_regs = false; @@ -504,6 +623,71 @@ int sde_splash_smmu_map(struct drm_device *dev, struct msm_mmu *mmu, return ret ? 0 : -ENOMEM; } +static bool _sde_splash_get_panel_intf_status(struct sde_splash_info *sinfo, + const char *display_name, int connector_type) +{ + bool ret = false; + int intf_status = 0; + + if (sinfo && sinfo->handoff) { + if (connector_type == DRM_MODE_CONNECTOR_DSI) { + if (!strcmp(display_name, "dsi_adv_7533_1")) { + if (sinfo->intf_sel_status & INTF_DSI0_SEL) + ret = true; + } else if (!strcmp(display_name, "dsi_adv_7533_2")) { + if (sinfo->intf_sel_status & INTF_DSI1_SEL) + ret = true; + } else + DRM_INFO("wrong display name %s\n", + display_name); + } else if (connector_type == DRM_MODE_CONNECTOR_HDMIA) { + intf_status = sinfo->intf_sel_status & INTF_HDMI_SEL; + ret = (intf_status == INTF_HDMI_SEL); + } + } + + return ret; +} + +int sde_splash_setup_display_resource(struct sde_splash_info *sinfo, + void *disp, int connector_type) +{ + if (!sinfo || !disp) + return -EINVAL; + + /* early return if splash is not enabled in bootloader */ + if (!sinfo->handoff) + return 0; + + if (connector_type == DRM_MODE_CONNECTOR_DSI) { + struct dsi_display *display = (struct dsi_display *)disp; + + display->cont_splash_enabled = + _sde_splash_get_panel_intf_status(sinfo, + display->name, + connector_type); + + DRM_INFO("DSI splash %s\n", + display->cont_splash_enabled ? "enabled" : "disabled"); + + if (display->cont_splash_enabled) { + if (dsi_dsiplay_setup_splash_resource(display)) + return -EINVAL; + } + } else if (connector_type == DRM_MODE_CONNECTOR_HDMIA) { + struct sde_hdmi *sde_hdmi = (struct sde_hdmi *)disp; + + sde_hdmi->cont_splash_enabled = + _sde_splash_get_panel_intf_status(sinfo, + NULL, connector_type); + + DRM_INFO("HDMI splash %s\n", + sde_hdmi->cont_splash_enabled ? "enabled" : "disabled"); + } + + return 0; +} + void sde_splash_setup_connector_count(struct sde_splash_info *sinfo, int connector_type) { @@ -578,6 +762,8 @@ int sde_splash_clean_up_free_resource(struct msm_kms *kms, sde_power_data_bus_bandwidth_ctrl(phandle, sde_kms->core_client, false); + _sde_splash_sent_pipe_update_uevent(sde_kms); + mutex_unlock(&sde_splash_lock); return 0; } diff --git a/drivers/gpu/drm/msm/sde/sde_splash.h b/drivers/gpu/drm/msm/sde/sde_splash.h index babf88335e49..9eddd87e5e26 100644 --- a/drivers/gpu/drm/msm/sde/sde_splash.h +++ b/drivers/gpu/drm/msm/sde/sde_splash.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 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 @@ -49,11 +49,20 @@ struct sde_splash_info { /* memory size of lk pool */ size_t lk_pool_size; + /* enabled statue of displays*/ + uint32_t intf_sel_status; + + /* DSI split enabled flag */ + bool split_is_enabled; + /* registered hdmi connector count */ uint32_t hdmi_connector_cnt; /* registered dst connector count */ uint32_t dsi_connector_cnt; + + /* reserved pipe info for early RVC */ + uint32_t reserved_pipe_info[MAX_BLOCKS]; }; /* APIs for early splash handoff functions */ @@ -99,11 +108,27 @@ int sde_splash_clean_up_free_resource(struct msm_kms *kms, int connector_type, void *display); /** - * sde_splash_parse_dt. + * sde_splash_parse_memory_dt. * * Parse reserved memory block from DT for early splash. */ -int sde_splash_parse_dt(struct drm_device *dev); +int sde_splash_parse_memory_dt(struct drm_device *dev); + +/** + * sde_splash_parse_reserved_plane_dt + * + * Parse reserved plane information from DT for early RVC case. + */ +int sde_splash_parse_reserved_plane_dt(struct sde_splash_info *splash_info, + struct sde_mdss_cfg *cfg); + +/* + * sde_splash_query_plane_is_reserved + * + * Query plane is reserved in dt. + */ +bool sde_splash_query_plane_is_reserved(struct sde_splash_info *sinfo, + uint32_t pipe); /** * sde_splash_smmu_map. @@ -129,4 +154,11 @@ void sde_splash_destroy(struct sde_splash_info *sinfo, */ bool sde_splash_get_lk_complete_status(struct sde_splash_info *sinfo); +/** + * sde_splash_setup_display_resource + * + * Setup display resource based on connector type. + */ +int sde_splash_setup_display_resource(struct sde_splash_info *sinfo, + void *disp, int connector_type); #endif diff --git a/drivers/i2c/busses/i2c-msm-v2.c b/drivers/i2c/busses/i2c-msm-v2.c index c0d962212720..67261bc10e80 100644 --- a/drivers/i2c/busses/i2c-msm-v2.c +++ b/drivers/i2c/busses/i2c-msm-v2.c @@ -2848,8 +2848,8 @@ static void i2c_msm_pm_rt_init(struct device *dev) {} static const struct dev_pm_ops i2c_msm_pm_ops = { #ifdef CONFIG_PM_SLEEP - .suspend_noirq = i2c_msm_pm_sys_suspend_noirq, - .resume_noirq = i2c_msm_pm_sys_resume_noirq, + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(i2c_msm_pm_sys_suspend_noirq, + i2c_msm_pm_sys_resume_noirq) #endif SET_RUNTIME_PM_OPS(i2c_msm_pm_rt_suspend, i2c_msm_pm_rt_resume, diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c index a58775953242..c90633b16fad 100644 --- a/drivers/leds/leds-qpnp-flash-v2.c +++ b/drivers/leds/leds-qpnp-flash-v2.c @@ -319,7 +319,7 @@ static inline int get_current_reg_code(int target_curr_ma, int ires_ua) if (!ires_ua || !target_curr_ma || (target_curr_ma < (ires_ua / 1000))) return 0; - return DIV_ROUND_UP(target_curr_ma * 1000, ires_ua) - 1; + return DIV_ROUND_CLOSEST(target_curr_ma * 1000, ires_ua) - 1; } static int qpnp_flash_led_read(struct qpnp_flash_led *led, u16 addr, u8 *data) diff --git a/drivers/media/i2c/adv7481.c b/drivers/media/i2c/adv7481.c index 9c8159cc737a..43a5f3da5ac4 100644 --- a/drivers/media/i2c/adv7481.c +++ b/drivers/media/i2c/adv7481.c @@ -55,6 +55,8 @@ #define LOCK_MAX_SLEEP 6000 #define LOCK_NUM_TRIES 200 +#define MAX_DEFAULT_WIDTH 1280 +#define MAX_DEFAULT_HEIGHT 720 #define MAX_DEFAULT_FRAME_RATE 60 #define MAX_DEFAULT_PIX_CLK_HZ 74240000 @@ -1705,7 +1707,8 @@ static int adv7481_get_hdmi_timings(struct adv7481_state *state, } else { pr_err("%s(%d): PLL not locked return EBUSY\n", __func__, __LINE__); - return -EBUSY; + ret = -EBUSY; + goto set_default; } /* Check Timing Lock */ @@ -1825,6 +1828,17 @@ static int adv7481_get_hdmi_timings(struct adv7481_state *state, (hdmi_params->pix_rep + 1)); } +set_default: + if (ret) { + pr_debug("%s(%d), error %d resort to default fmt\n", + __func__, __LINE__, ret); + vid_params->act_pix = MAX_DEFAULT_WIDTH; + vid_params->act_lines = MAX_DEFAULT_HEIGHT; + vid_params->fr_rate = MAX_DEFAULT_FRAME_RATE; + vid_params->pix_clk = MAX_DEFAULT_PIX_CLK_HZ; + vid_params->intrlcd = 0; + ret = 0; + } pr_debug("%s(%d), adv7481 TMDS Resolution: %d x %d @ %d fps\n", __func__, __LINE__, diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_3_5_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_3_5_hwreg.h index 6ed5c5c7dbce..323f99f25147 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_3_5_hwreg.h +++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_3_5_hwreg.h @@ -14,7 +14,6 @@ #define MSM_CSIPHY_3_5_HWREG_H #define ULPM_WAKE_UP_TIMER_MODE 2 -#define GLITCH_ELIMINATION_NUM 0x12 /* bit [6:4] */ #include <sensor/csiphy/msm_csiphy.h> @@ -47,7 +46,7 @@ struct csiphy_reg_3ph_parms_t csiphy_v3_5_3ph = { {0x138, 0x0}, {0x13C, 0x10}, {0x140, 0x1}, - {0x144, GLITCH_ELIMINATION_NUM}, + {0x144, 0x32}, {0x148, 0xFE}, {0x14C, 0x1}, {0x154, 0x0}, diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c index a8d7c1f8b489..4f7a62716810 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c +++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2018, 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 @@ -52,6 +52,7 @@ #define MAX_DPHY_DATA_LN 4 #define CLOCK_OFFSET 0x700 #define CSIPHY_SOF_DEBUG_COUNT 2 +#define GBPS 1000000000 #undef CDBG #define CDBG(fmt, args...) pr_debug(fmt, ##args) @@ -134,8 +135,10 @@ static int msm_csiphy_3phase_lane_config( uint8_t i = 0; uint16_t lane_mask = 0, lane_enable = 0, temp; void __iomem *csiphybase; + uint64_t two_gbps = 0; csiphybase = csiphy_dev->base; + two_gbps = 2 * (uint64_t)csiphy_params->lane_cnt * GBPS; lane_mask = csiphy_params->lane_mask & 0x7; while (lane_mask != 0) { temp = (i << 1)+1; @@ -281,11 +284,20 @@ static int msm_csiphy_3phase_lane_config( csiphy_3ph_reg.mipi_csiphy_3ph_lnn_ctrl51.addr + 0x200*i); } - msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_3ph_lnn_ctrl25.data, - csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. - mipi_csiphy_3ph_lnn_ctrl25.addr + 0x200*i); + if ((csiphy_dev->hw_version == CSIPHY_VERSION_V35) && + (csiphy_params->data_rate > two_gbps)) { + msm_camera_io_w(0x40, + csiphybase + + csiphy_dev->ctrl_reg->csiphy_3ph_reg. + mipi_csiphy_3ph_lnn_ctrl25.addr + 0x200*i); + } else { + msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg. + mipi_csiphy_3ph_lnn_ctrl25.data, + csiphybase + + csiphy_dev->ctrl_reg->csiphy_3ph_reg. + mipi_csiphy_3ph_lnn_ctrl25.addr + 0x200*i); + } lane_mask >>= 1; i++; } @@ -797,10 +809,10 @@ static int msm_csiphy_lane_config(struct csiphy_device *csiphy_dev, ratio = csiphy_dev->csiphy_max_clk/clk_rate; csiphy_params->settle_cnt = csiphy_params->settle_cnt/ratio; } - CDBG("%s csiphy_params, mask = 0x%x cnt = %d\n", + CDBG("%s csiphy_params, mask = 0x%x cnt = %d, data rate = %llu\n", __func__, csiphy_params->lane_mask, - csiphy_params->lane_cnt); + csiphy_params->lane_cnt, csiphy_params->data_rate); CDBG("%s csiphy_params, settle cnt = 0x%x csid %d\n", __func__, csiphy_params->settle_cnt, csiphy_params->csid_core); diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index de7def1f4f1c..35be47dafda2 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -3614,7 +3614,7 @@ void mmc_blk_cmdq_complete_rq(struct request *rq) * or disable state so cannot receive any completion of * other requests. */ - BUG_ON(test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state)); + WARN_ON(test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state)); /* clear pending request */ BUG_ON(!test_and_clear_bit(cmdq_req->tag, @@ -3648,7 +3648,7 @@ void mmc_blk_cmdq_complete_rq(struct request *rq) out: mmc_cmdq_clk_scaling_stop_busy(host, true, is_dcmd); - if (!test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state)) { + if (!(err || cmdq_req->resp_err)) { mmc_host_clk_release(host); wake_up(&ctx_info->wait); mmc_put_card(host->card); diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 548a9e8b72ae..0b527a708bd7 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -373,12 +373,13 @@ int mmc_add_card(struct mmc_card *card) mmc_card_ddr52(card) ? "DDR " : "", type); } else { - pr_info("%s: new %s%s%s%s%s card at address %04x\n", + pr_info("%s: new %s%s%s%s%s%s card at address %04x\n", mmc_hostname(card->host), mmc_card_uhs(card) ? "ultra high speed " : (mmc_card_hs(card) ? "high speed " : ""), mmc_card_hs400(card) ? "HS400 " : (mmc_card_hs200(card) ? "HS200 " : ""), + mmc_card_hs400es(card) ? "Enhanced strobe " : "", mmc_card_ddr52(card) ? "DDR " : "", uhs_bus_speed_mode, type, card->rca); } diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 76170d20ef84..547d18c9feef 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1170,6 +1170,46 @@ static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) return 0; } +static int mmc_cmdq_check_retune(struct mmc_host *host) +{ + bool cmdq_mode; + int err = 0; + + if (!host->need_retune || host->doing_retune || !host->card || + mmc_card_hs400es(host->card) || + (host->ios.clock <= MMC_HIGH_DDR_MAX_DTR)) + return 0; + + cmdq_mode = mmc_card_cmdq(host->card); + if (cmdq_mode) { + err = mmc_cmdq_halt(host, true); + if (err) { + pr_err("%s: %s: failed halting queue (%d)\n", + mmc_hostname(host), __func__, err); + host->cmdq_ops->dumpstate(host); + goto halt_failed; + } + } + + mmc_retune_hold(host); + err = mmc_retune(host); + mmc_retune_release(host); + + if (cmdq_mode) { + if (mmc_cmdq_halt(host, false)) { + pr_err("%s: %s: cmdq unhalt failed\n", + mmc_hostname(host), __func__); + host->cmdq_ops->dumpstate(host); + } + } + +halt_failed: + pr_debug("%s: %s: Retuning done err: %d\n", + mmc_hostname(host), __func__, err); + + return err; +} + static int mmc_start_cmdq_request(struct mmc_host *host, struct mmc_request *mrq) { @@ -1196,6 +1236,7 @@ static int mmc_start_cmdq_request(struct mmc_host *host, } mmc_host_clk_hold(host); + mmc_cmdq_check_retune(host); if (likely(host->cmdq_ops->request)) { ret = host->cmdq_ops->request(host, mrq); } else { @@ -1558,7 +1599,8 @@ static void mmc_wait_for_req_done(struct mmc_host *host, mmc_card_removed(host->card)) { if (cmd->error && !cmd->retries && cmd->opcode != MMC_SEND_STATUS && - cmd->opcode != MMC_SEND_TUNING_BLOCK) + cmd->opcode != MMC_SEND_TUNING_BLOCK && + cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) mmc_recovery_fallback_lower_speed(host); break; } @@ -2969,8 +3011,16 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr) */ mmc_host_clk_hold(host); err = mmc_wait_for_cmd(host, &cmd, 0); - if (err) - goto err_command; + if (err) { + if (err == -ETIMEDOUT) { + pr_debug("%s: voltage switching failed with err %d\n", + mmc_hostname(host), err); + err = -EAGAIN; + goto power_cycle; + } else { + goto err_command; + } + } if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR)) { err = -EIO; diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index e63ec61fed3c..b3b9d78f789a 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -388,7 +388,8 @@ int mmc_retune(struct mmc_host *host) else return 0; - if (!host->need_retune || host->doing_retune || !host->card) + if (!host->need_retune || host->doing_retune || !host->card || + mmc_card_hs400es(host->card)) return 0; host->need_retune = 0; diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 6f4f81a370d8..c8f85b31e2ac 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1275,6 +1275,8 @@ static int mmc_select_hs400(struct mmc_card *card) if (card->ext_csd.strobe_support && host->ops->enhanced_strobe) { mmc_host_clk_hold(host); err = host->ops->enhanced_strobe(host); + if (!err) + host->ios.enhanced_strobe = true; mmc_host_clk_release(host); } else if ((host->caps2 & MMC_CAP2_HS400_POST_TUNING) && host->ops->execute_tuning) { diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index fe86dc84d9c3..008fd633cb5d 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -5665,6 +5665,22 @@ static void ath10k_set_key_h_def_keyidx(struct ath10k *ar, arvif->vdev_id, ret); } +static void ath10k_set_rekey_data(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_gtk_rekey_data *data) +{ + struct ath10k *ar = hw->priv; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + + mutex_lock(&ar->conf_mutex); + memcpy(&arvif->gtk_rekey_data.kek, data->kek, NL80211_KEK_LEN); + memcpy(&arvif->gtk_rekey_data.kck, data->kck, NL80211_KCK_LEN); + arvif->gtk_rekey_data.replay_ctr = + be64_to_cpup((__be64 *)data->replay_ctr); + arvif->gtk_rekey_data.valid = true; + mutex_unlock(&ar->conf_mutex); +} + static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) @@ -7609,6 +7625,7 @@ static const struct ieee80211_ops ath10k_ops = { .bss_info_changed = ath10k_bss_info_changed, .hw_scan = ath10k_hw_scan, .cancel_hw_scan = ath10k_cancel_hw_scan, + .set_rekey_data = ath10k_set_rekey_data, .set_key = ath10k_set_key, .set_default_unicast_key = ath10k_set_default_unicast_key, .sta_state = ath10k_sta_state, @@ -7644,7 +7661,6 @@ static const struct ieee80211_ops ath10k_ops = { .suspend = ath10k_wow_op_suspend, .resume = ath10k_wow_op_resume, .set_wakeup = ath10k_wow_op_set_wakeup, - .set_rekey_data = ath10k_wow_op_set_rekey_data, #endif #ifdef CONFIG_MAC80211_DEBUGFS .sta_add_debugfs = ath10k_sta_add_debugfs, diff --git a/drivers/net/wireless/ath/ath10k/wow.c b/drivers/net/wireless/ath/ath10k/wow.c index 69066efbb2a8..2280f47dc227 100644 --- a/drivers/net/wireless/ath/ath10k/wow.c +++ b/drivers/net/wireless/ath/ath10k/wow.c @@ -445,22 +445,6 @@ static int ath10k_config_wow_listen_interval(struct ath10k *ar) return 0; } -void ath10k_wow_op_set_rekey_data(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct cfg80211_gtk_rekey_data *data) -{ - struct ath10k *ar = hw->priv; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); - - mutex_lock(&ar->conf_mutex); - memcpy(&arvif->gtk_rekey_data.kek, data->kek, NL80211_KEK_LEN); - memcpy(&arvif->gtk_rekey_data.kck, data->kck, NL80211_KCK_LEN); - arvif->gtk_rekey_data.replay_ctr = - cpu_to_le64(be64_to_cpup((__be64 *)data->replay_ctr)); - arvif->gtk_rekey_data.valid = true; - mutex_unlock(&ar->conf_mutex); -} - static int ath10k_wow_config_gtk_offload(struct ath10k *ar, bool gtk_offload) { struct ath10k_vif *arvif; @@ -509,6 +493,13 @@ int ath10k_wow_op_suspend(struct ieee80211_hw *hw, goto exit; } + ret = ath10k_wow_cleanup(ar); + if (ret) { + ath10k_warn(ar, "failed to clear wow wakeup events: %d\n", + ret); + goto exit; + } + ret = ath10k_wow_config_gtk_offload(ar, true); if (ret) { ath10k_warn(ar, "failed to enable GTK offload: %d\n", ret); @@ -521,18 +512,11 @@ int ath10k_wow_op_suspend(struct ieee80211_hw *hw, goto disable_gtk_offload; } - ret = ath10k_wow_cleanup(ar); - if (ret) { - ath10k_warn(ar, "failed to clear wow wakeup events: %d\n", - ret); - goto disable_ns_arp_offload; - } - ret = ath10k_wow_set_wakeups(ar, wowlan); if (ret) { ath10k_warn(ar, "failed to set wow wakeup events: %d\n", ret); - goto cleanup; + goto disable_ns_arp_offload; } ret = ath10k_config_wow_listen_interval(ar); diff --git a/drivers/net/wireless/ath/ath10k/wow.h b/drivers/net/wireless/ath/ath10k/wow.h index a33881739138..2ca4ba4848c9 100644 --- a/drivers/net/wireless/ath/ath10k/wow.h +++ b/drivers/net/wireless/ath/ath10k/wow.h @@ -32,9 +32,6 @@ int ath10k_wow_op_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan); int ath10k_wow_op_resume(struct ieee80211_hw *hw); void ath10k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled); -void ath10k_wow_op_set_rekey_data(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct cfg80211_gtk_rekey_data *data); #else static inline int ath10k_wow_init(struct ath10k *ar) diff --git a/drivers/net/wireless/cnss/cnss_pci.c b/drivers/net/wireless/cnss/cnss_pci.c index af92f00ca56e..03219cf1693a 100644 --- a/drivers/net/wireless/cnss/cnss_pci.c +++ b/drivers/net/wireless/cnss/cnss_pci.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, 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 @@ -569,6 +569,7 @@ out: static void cnss_wlan_gpio_set(struct cnss_wlan_gpio_info *info, bool state) { +#ifndef CONFIG_MSM_GVM_QUIN if (!info->prop) return; @@ -588,6 +589,9 @@ static void cnss_wlan_gpio_set(struct cnss_wlan_gpio_info *info, bool state) pr_debug("%s: %s gpio is now %s\n", __func__, info->name, info->state ? "enabled" : "disabled"); +#else + return; +#endif } static int cnss_configure_wlan_en_gpio(bool state) @@ -1560,7 +1564,6 @@ int cnss_msm_pcie_enumerate(u32 rc_idx) return msm_pcie_enumerate(rc_idx); } #else /* !defined CONFIG_PCI_MSM */ - struct pci_saved_state *cnss_pci_store_saved_state(struct pci_dev *dev) { return NULL; @@ -1570,7 +1573,7 @@ int cnss_msm_pcie_pm_control( enum msm_pcie_pm_opt pm_opt, u32 bus_num, struct pci_dev *pdev, u32 options) { - return -ENODEV; + return 0; } int cnss_pci_load_and_free_saved_state( @@ -1581,27 +1584,27 @@ int cnss_pci_load_and_free_saved_state( int cnss_msm_pcie_shadow_control(struct pci_dev *dev, bool enable) { - return -ENODEV; + return 0; } int cnss_msm_pcie_deregister_event(struct msm_pcie_register_event *reg) { - return -ENODEV; + return 0; } int cnss_msm_pcie_recover_config(struct pci_dev *dev) { - return -ENODEV; + return 0; } int cnss_msm_pcie_register_event(struct msm_pcie_register_event *reg) { - return -ENODEV; + return 0; } int cnss_msm_pcie_enumerate(u32 rc_idx) { - return -EPROBE_DEFER; + return 0; } #endif @@ -2870,7 +2873,9 @@ static int cnss_probe(struct platform_device *pdev) struct esoc_desc *desc; const char *client_desc; struct device *dev = &pdev->dev; +#ifndef CONFIG_MSM_GVM_QUIN u32 rc_num; +#endif struct resource *res; u32 ramdump_size = 0; u32 smmu_iova_address[2]; @@ -2905,6 +2910,7 @@ static int cnss_probe(struct platform_device *pdev) goto err_get_rc; } +#ifndef CONFIG_MSM_GVM_QUIN ret = of_property_read_u32(dev->of_node, "qcom,wlan-rc-num", &rc_num); if (ret) { pr_err("%s: Failed to find PCIe RC number!\n", __func__); @@ -2916,6 +2922,7 @@ static int cnss_probe(struct platform_device *pdev) pr_err("%s: Failed to enable PCIe RC%x!\n", __func__, rc_num); goto err_pcie_enumerate; } +#endif penv->pcie_link_state = PCIE_LINK_UP; @@ -3096,7 +3103,9 @@ err_subsys_reg: devm_unregister_esoc_client(&pdev->dev, penv->esoc_desc); err_esoc_reg: +#ifndef CONFIG_MSM_GVM_QUIN err_pcie_enumerate: +#endif err_get_rc: cnss_configure_wlan_en_gpio(WLAN_EN_LOW); cnss_wlan_release_resources(); diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c index dcaf3203f197..fc35b0892768 100644 --- a/drivers/net/wireless/cnss2/main.c +++ b/drivers/net/wireless/cnss2/main.c @@ -1690,6 +1690,7 @@ static int cnss_cold_boot_cal_start_hdlr(struct cnss_plat_data *plat_priv) static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv) { + plat_priv->cal_done = true; cnss_wlfw_wlan_mode_send_sync(plat_priv, QMI_WLFW_OFF_V01); cnss_shutdown(plat_priv); clear_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state); diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h index f658b6d391b8..a36281cb560f 100644 --- a/drivers/net/wireless/cnss2/main.h +++ b/drivers/net/wireless/cnss2/main.h @@ -107,6 +107,7 @@ struct cnss_fw_mem { void *va; phys_addr_t pa; bool valid; + u32 type; }; enum cnss_driver_event_type { @@ -192,7 +193,8 @@ struct cnss_plat_data { struct wlfw_rf_board_info_s_v01 board_info; struct wlfw_soc_info_s_v01 soc_info; struct wlfw_fw_version_info_s_v01 fw_version_info; - struct cnss_fw_mem fw_mem; + u32 fw_mem_seg_len; + struct cnss_fw_mem fw_mem[QMI_WLFW_MAX_NUM_MEM_SEG_V01]; struct cnss_fw_mem m3_mem; struct cnss_pin_connect_result pin_result; struct dentry *root_dentry; @@ -204,6 +206,7 @@ struct cnss_plat_data { u32 diag_reg_read_mem_type; u32 diag_reg_read_len; u8 *diag_reg_read_buf; + bool cal_done; }; void *cnss_bus_dev_to_bus_priv(struct device *dev); diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index 2ee0edda1b5b..5746366ff852 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -737,18 +737,21 @@ int cnss_pm_request_resume(struct cnss_pci_data *pci_priv) int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv) { struct cnss_plat_data *plat_priv = pci_priv->plat_priv; - struct cnss_fw_mem *fw_mem = &plat_priv->fw_mem; - - if (!fw_mem->va && fw_mem->size) { - fw_mem->va = dma_alloc_coherent(&pci_priv->pci_dev->dev, - fw_mem->size, &fw_mem->pa, - GFP_KERNEL); - if (!fw_mem->va) { - cnss_pr_err("Failed to allocate memory for FW, size: 0x%zx\n", - fw_mem->size); - fw_mem->size = 0; - - return -ENOMEM; + struct cnss_fw_mem *fw_mem = plat_priv->fw_mem; + int i; + + for (i = 0; i < plat_priv->fw_mem_seg_len; i++) { + if (!fw_mem[i].va && fw_mem[i].size) { + fw_mem[i].va = + dma_alloc_coherent(&pci_priv->pci_dev->dev, + fw_mem[i].size, + &fw_mem[i].pa, GFP_KERNEL); + if (!fw_mem[i].va) { + cnss_pr_err("Failed to allocate memory for FW, size: 0x%zx, type: %u\n", + fw_mem[i].size, fw_mem[i].type); + + return -ENOMEM; + } } } @@ -758,17 +761,25 @@ int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv) static void cnss_pci_free_fw_mem(struct cnss_pci_data *pci_priv) { struct cnss_plat_data *plat_priv = pci_priv->plat_priv; - struct cnss_fw_mem *fw_mem = &plat_priv->fw_mem; - - if (fw_mem->va && fw_mem->size) { - cnss_pr_dbg("Freeing memory for FW, va: 0x%pK, pa: %pa, size: 0x%zx\n", - fw_mem->va, &fw_mem->pa, fw_mem->size); - dma_free_coherent(&pci_priv->pci_dev->dev, fw_mem->size, - fw_mem->va, fw_mem->pa); - fw_mem->va = NULL; - fw_mem->pa = 0; - fw_mem->size = 0; + struct cnss_fw_mem *fw_mem = plat_priv->fw_mem; + int i; + + for (i = 0; i < plat_priv->fw_mem_seg_len; i++) { + if (fw_mem[i].va && fw_mem[i].size) { + cnss_pr_dbg("Freeing memory for FW, va: 0x%pK, pa: %pa, size: 0x%zx, type: %u\n", + fw_mem[i].va, &fw_mem[i].pa, + fw_mem[i].size, fw_mem[i].type); + dma_free_coherent(&pci_priv->pci_dev->dev, + fw_mem[i].size, fw_mem[i].va, + fw_mem[i].pa); + fw_mem[i].va = NULL; + fw_mem[i].pa = 0; + fw_mem[i].size = 0; + fw_mem[i].type = 0; + } } + + plat_priv->fw_mem_seg_len = 0; } int cnss_pci_load_m3(struct cnss_pci_data *pci_priv) diff --git a/drivers/net/wireless/cnss2/qmi.c b/drivers/net/wireless/cnss2/qmi.c index f4344aee54ee..b8777c18d252 100644 --- a/drivers/net/wireless/cnss2/qmi.c +++ b/drivers/net/wireless/cnss2/qmi.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, 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 @@ -159,10 +159,9 @@ static int cnss_wlfw_host_cap_send_sync(struct cnss_plat_data *plat_priv) memset(&req, 0, sizeof(req)); memset(&resp, 0, sizeof(resp)); - req.daemon_support_valid = 1; - req.daemon_support = daemon_support; - - cnss_pr_dbg("daemon_support is %d\n", req.daemon_support); + req.num_clients_valid = 1; + req.num_clients = daemon_support ? 2 : 1; + cnss_pr_dbg("Number of clients is %d\n", req.num_clients); req.wake_msi = cnss_get_wake_msi(plat_priv); if (req.wake_msi) { @@ -170,6 +169,19 @@ static int cnss_wlfw_host_cap_send_sync(struct cnss_plat_data *plat_priv) req.wake_msi_valid = 1; } + req.bdf_support_valid = 1; + req.bdf_support = 1; + + req.m3_support_valid = 1; + req.m3_support = 1; + + req.m3_cache_support_valid = 1; + req.m3_cache_support = 1; + + req.cal_done_valid = 1; + req.cal_done = plat_priv->cal_done; + cnss_pr_dbg("Calibration done is %d\n", plat_priv->cal_done); + req_desc.max_msg_len = WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN; req_desc.msg_id = QMI_WLFW_HOST_CAP_REQ_V01; req_desc.ei_array = wlfw_host_cap_req_msg_v01_ei; @@ -221,8 +233,8 @@ static int cnss_wlfw_ind_register_send_sync(struct cnss_plat_data *plat_priv) req.request_mem_enable = 1; req.fw_mem_ready_enable_valid = 1; req.fw_mem_ready_enable = 1; - req.cold_boot_cal_done_enable_valid = 1; - req.cold_boot_cal_done_enable = 1; + req.fw_init_done_enable_valid = 1; + req.fw_init_done_enable = 1; req.pin_connect_result_enable_valid = 1; req.pin_connect_result_enable = 1; @@ -260,27 +272,48 @@ static int cnss_wlfw_request_mem_ind_hdlr(struct cnss_plat_data *plat_priv, void *msg, unsigned int msg_len) { struct msg_desc ind_desc; - struct wlfw_request_mem_ind_msg_v01 ind_msg; - struct cnss_fw_mem *fw_mem = &plat_priv->fw_mem; - int ret = 0; + struct wlfw_request_mem_ind_msg_v01 *ind_msg; + int ret = 0, i; + + ind_msg = kzalloc(sizeof(*ind_msg), GFP_KERNEL); + if (!ind_msg) + return -ENOMEM; ind_desc.msg_id = QMI_WLFW_REQUEST_MEM_IND_V01; ind_desc.max_msg_len = WLFW_REQUEST_MEM_IND_MSG_V01_MAX_MSG_LEN; ind_desc.ei_array = wlfw_request_mem_ind_msg_v01_ei; - ret = qmi_kernel_decode(&ind_desc, &ind_msg, msg, msg_len); + ret = qmi_kernel_decode(&ind_desc, ind_msg, msg, msg_len); if (ret < 0) { cnss_pr_err("Failed to decode request memory indication, msg_len: %u, err = %d\n", ret, msg_len); - return ret; + goto out; } - fw_mem->size = ind_msg.size; + if (ind_msg->mem_seg_len == 0 || + ind_msg->mem_seg_len > QMI_WLFW_MAX_NUM_MEM_SEG_V01) { + cnss_pr_err("Invalid memory segment length: %u\n", + ind_msg->mem_seg_len); + ret = -EINVAL; + goto out; + } + + cnss_pr_dbg("FW memory segment count is %u\n", ind_msg->mem_seg_len); + plat_priv->fw_mem_seg_len = ind_msg->mem_seg_len; + for (i = 0; i < plat_priv->fw_mem_seg_len; i++) { + plat_priv->fw_mem[i].type = ind_msg->mem_seg[i].type; + plat_priv->fw_mem[i].size = ind_msg->mem_seg[i].size; + } cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_REQUEST_MEM, 0, NULL); + kfree(ind_msg); return 0; + +out: + kfree(ind_msg); + return ret; } static int cnss_qmi_pin_result_ind_hdlr(struct cnss_plat_data *plat_priv, @@ -317,29 +350,46 @@ static int cnss_qmi_pin_result_ind_hdlr(struct cnss_plat_data *plat_priv, int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv) { - struct wlfw_respond_mem_req_msg_v01 req; - struct wlfw_respond_mem_resp_msg_v01 resp; + struct wlfw_respond_mem_req_msg_v01 *req; + struct wlfw_respond_mem_resp_msg_v01 *resp; struct msg_desc req_desc, resp_desc; - struct cnss_fw_mem *fw_mem = &plat_priv->fw_mem; - int ret = 0; + struct cnss_fw_mem *fw_mem = plat_priv->fw_mem; + int ret = 0, i; cnss_pr_dbg("Sending respond memory message, state: 0x%lx\n", plat_priv->driver_state); - if (!fw_mem->pa || !fw_mem->size) { - cnss_pr_err("Memory for FW is not available!\n"); - ret = -ENOMEM; - goto out; - } + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (!req) + return -ENOMEM; + + resp = kzalloc(sizeof(*resp), GFP_KERNEL); + if (!resp) + return -ENOMEM; - cnss_pr_dbg("Memory for FW, va: 0x%pK, pa: %pa, size: 0x%zx\n", - fw_mem->va, &fw_mem->pa, fw_mem->size); + req->mem_seg_len = plat_priv->fw_mem_seg_len; + for (i = 0; i < req->mem_seg_len; i++) { + if (!fw_mem[i].pa || !fw_mem[i].size) { + if (fw_mem[i].type == 0) { + cnss_pr_err("Invalid memory for FW type, segment = %d\n", + i); + ret = -EINVAL; + goto out; + } + cnss_pr_err("Memory for FW is not available for type: %u\n", + fw_mem[i].type); + ret = -ENOMEM; + goto out; + } - memset(&req, 0, sizeof(req)); - memset(&resp, 0, sizeof(resp)); + cnss_pr_dbg("Memory for FW, va: 0x%pK, pa: %pa, size: 0x%zx, type: %u\n", + fw_mem[i].va, &fw_mem[i].pa, + fw_mem[i].size, fw_mem[i].type); - req.addr = fw_mem->pa; - req.size = fw_mem->size; + req->mem_seg[i].addr = fw_mem[i].pa; + req->mem_seg[i].size = fw_mem[i].size; + req->mem_seg[i].type = fw_mem[i].type; + } req_desc.max_msg_len = WLFW_RESPOND_MEM_REQ_MSG_V01_MAX_MSG_LEN; req_desc.msg_id = QMI_WLFW_RESPOND_MEM_REQ_V01; @@ -349,8 +399,8 @@ int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv) resp_desc.msg_id = QMI_WLFW_RESPOND_MEM_RESP_V01; resp_desc.ei_array = wlfw_respond_mem_resp_msg_v01_ei; - ret = qmi_send_req_wait(plat_priv->qmi_wlfw_clnt, &req_desc, &req, - sizeof(req), &resp_desc, &resp, sizeof(resp), + ret = qmi_send_req_wait(plat_priv->qmi_wlfw_clnt, &req_desc, req, + sizeof(*req), &resp_desc, resp, sizeof(*resp), QMI_WLFW_TIMEOUT_MS); if (ret < 0) { cnss_pr_err("Failed to send respond memory request, err = %d\n", @@ -358,16 +408,21 @@ int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv) goto out; } - if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { + if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { cnss_pr_err("Respond memory request failed, result: %d, err: %d\n", - resp.resp.result, resp.resp.error); - ret = resp.resp.result; + resp->resp.result, resp->resp.error); + ret = resp->resp.result; goto out; } + kfree(req); + kfree(resp); return 0; + out: CNSS_ASSERT(0); + kfree(req); + kfree(resp); return ret; } @@ -908,12 +963,12 @@ static void cnss_wlfw_clnt_ind(struct qmi_handle *handle, CNSS_DRIVER_EVENT_FW_MEM_READY, 0, NULL); break; - case QMI_WLFW_COLD_BOOT_CAL_DONE_IND_V01: + case QMI_WLFW_FW_READY_IND_V01: cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE, 0, NULL); break; - case QMI_WLFW_FW_READY_IND_V01: + case QMI_WLFW_FW_INIT_DONE_IND_V01: cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_FW_READY, 0, NULL); @@ -974,11 +1029,11 @@ int cnss_wlfw_server_arrive(struct cnss_plat_data *plat_priv) cnss_pr_info("QMI WLFW service connected, state: 0x%lx\n", plat_priv->driver_state); - ret = cnss_wlfw_host_cap_send_sync(plat_priv); + ret = cnss_wlfw_ind_register_send_sync(plat_priv); if (ret < 0) goto out; - ret = cnss_wlfw_ind_register_send_sync(plat_priv); + ret = cnss_wlfw_host_cap_send_sync(plat_priv); if (ret < 0) goto out; diff --git a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c index 7d6a771bc0d5..bbf707b869bd 100644 --- a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c +++ b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, 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 @@ -62,7 +62,7 @@ static struct elem_info wlfw_ce_tgt_pipe_cfg_s_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -97,7 +97,7 @@ static struct elem_info wlfw_ce_svc_pipe_cfg_s_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -123,7 +123,7 @@ static struct elem_info wlfw_shadow_reg_cfg_s_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -140,7 +140,7 @@ static struct elem_info wlfw_shadow_reg_v2_cfg_s_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -175,7 +175,131 @@ static struct elem_info wlfw_memory_region_info_s_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct elem_info wlfw_mem_cfg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .is_array = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_cfg_s_v01, + offset), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .is_array = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_cfg_s_v01, + size), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_cfg_s_v01, + secure_flag), + }, + { + .data_type = QMI_EOTI, + .is_array = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct elem_info wlfw_mem_seg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .is_array = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_seg_s_v01, + size), + }, + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_mem_type_enum_v01), + .is_array = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_seg_s_v01, + type), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_seg_s_v01, + mem_cfg_len), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_NUM_MEM_CFG_V01, + .elem_size = sizeof(struct wlfw_mem_cfg_s_v01), + .is_array = VAR_LEN_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_seg_s_v01, + mem_cfg), + .ei_array = wlfw_mem_cfg_s_v01_ei, + }, + { + .data_type = QMI_EOTI, + .is_array = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct elem_info wlfw_mem_seg_resp_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .is_array = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, + addr), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .is_array = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, + size), + }, + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_mem_type_enum_v01), + .is_array = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, + type), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, + restore), + }, + { + .data_type = QMI_EOTI, + .is_array = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -201,7 +325,7 @@ static struct elem_info wlfw_rf_chip_info_s_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -218,7 +342,7 @@ static struct elem_info wlfw_rf_board_info_s_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -235,7 +359,7 @@ static struct elem_info wlfw_soc_info_s_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -261,7 +385,7 @@ static struct elem_info wlfw_fw_version_info_s_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -418,7 +542,7 @@ struct elem_info wlfw_ind_register_req_msg_v01_ei[] = { .is_array = NO_ARRAY, .tlv_type = 0x18, .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - cold_boot_cal_done_enable_valid), + fw_init_done_enable_valid), }, { .data_type = QMI_UNSIGNED_1_BYTE, @@ -427,7 +551,7 @@ struct elem_info wlfw_ind_register_req_msg_v01_ei[] = { .is_array = NO_ARRAY, .tlv_type = 0x18, .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - cold_boot_cal_done_enable), + fw_init_done_enable), }, { .data_type = QMI_OPT_FLAG, @@ -448,9 +572,45 @@ struct elem_info wlfw_ind_register_req_msg_v01_ei[] = { rejuvenate_enable), }, { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x1A, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + xo_cal_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x1A, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + xo_cal_enable), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x1B, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + cal_done_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x1B, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + cal_done_enable), + }, + { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -489,7 +649,7 @@ struct elem_info wlfw_ind_register_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -497,7 +657,7 @@ struct elem_info wlfw_fw_ready_ind_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -505,7 +665,7 @@ struct elem_info wlfw_msa_ready_ind_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -573,7 +733,7 @@ struct elem_info wlfw_pin_connect_result_ind_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -608,7 +768,7 @@ struct elem_info wlfw_wlan_mode_req_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -626,7 +786,7 @@ struct elem_info wlfw_wlan_mode_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -764,7 +924,7 @@ struct elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -782,7 +942,7 @@ struct elem_info wlfw_wlan_cfg_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -790,7 +950,7 @@ struct elem_info wlfw_cap_req_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -920,7 +1080,7 @@ struct elem_info wlfw_cap_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1054,7 +1214,7 @@ struct elem_info wlfw_bdf_download_req_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1073,7 +1233,7 @@ struct elem_info wlfw_bdf_download_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1117,7 +1277,7 @@ struct elem_info wlfw_cal_report_req_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1135,7 +1295,7 @@ struct elem_info wlfw_cal_report_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1153,7 +1313,7 @@ struct elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1269,7 +1429,7 @@ struct elem_info wlfw_cal_download_req_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1288,7 +1448,7 @@ struct elem_info wlfw_cal_download_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1316,7 +1476,7 @@ struct elem_info wlfw_initiate_cal_update_ind_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1342,7 +1502,7 @@ struct elem_info wlfw_cal_update_req_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1459,7 +1619,7 @@ struct elem_info wlfw_cal_update_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1485,7 +1645,7 @@ struct elem_info wlfw_msa_info_req_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1522,7 +1682,7 @@ struct elem_info wlfw_msa_info_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1530,7 +1690,7 @@ struct elem_info wlfw_msa_ready_req_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1548,7 +1708,7 @@ struct elem_info wlfw_msa_ready_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1574,7 +1734,7 @@ struct elem_info wlfw_ini_req_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1592,7 +1752,7 @@ struct elem_info wlfw_ini_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1627,7 +1787,7 @@ struct elem_info wlfw_athdiag_read_req_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1676,7 +1836,7 @@ struct elem_info wlfw_athdiag_read_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1724,7 +1884,7 @@ struct elem_info wlfw_athdiag_write_req_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1743,7 +1903,7 @@ struct elem_info wlfw_athdiag_write_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1760,7 +1920,7 @@ struct elem_info wlfw_vbatt_req_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1778,7 +1938,7 @@ struct elem_info wlfw_vbatt_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1804,7 +1964,7 @@ struct elem_info wlfw_mac_addr_req_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1822,7 +1982,7 @@ struct elem_info wlfw_mac_addr_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1834,16 +1994,16 @@ struct elem_info wlfw_host_cap_req_msg_v01_ei[] = { .is_array = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - daemon_support_valid), + num_clients_valid), }, { - .data_type = QMI_UNSIGNED_1_BYTE, + .data_type = QMI_UNSIGNED_4_BYTE, .elem_len = 1, - .elem_size = sizeof(u8), + .elem_size = sizeof(u32), .is_array = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - daemon_support), + num_clients), }, { .data_type = QMI_OPT_FLAG, @@ -1864,9 +2024,216 @@ struct elem_info wlfw_host_cap_req_msg_v01_ei[] = { wake_msi), }, { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + gpios_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + gpios_len), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = QMI_WLFW_MAX_NUM_GPIO_V01, + .elem_size = sizeof(u32), + .is_array = VAR_LEN_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + gpios), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + nm_modem_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + nm_modem), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + bdf_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + bdf_support), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + bdf_cache_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + bdf_cache_support), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x16, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + m3_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x16, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + m3_support), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x17, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + m3_cache_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x17, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + m3_cache_support), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x18, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_filesys_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x18, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_filesys_support), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x19, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_cache_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x19, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_cache_support), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x1A, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_done_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x1A, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_done), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x1B, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + mem_bucket_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .is_array = NO_ARRAY, + .tlv_type = 0x1B, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + mem_bucket), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x1C, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + mem_cfg_mode_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x1C, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + mem_cfg_mode), + }, + { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1884,50 +2251,61 @@ struct elem_info wlfw_host_cap_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; struct elem_info wlfw_request_mem_ind_msg_v01_ei[] = { { - .data_type = QMI_UNSIGNED_4_BYTE, + .data_type = QMI_DATA_LEN, .elem_len = 1, - .elem_size = sizeof(u32), + .elem_size = sizeof(u8), .is_array = NO_ARRAY, .tlv_type = 0x01, .offset = offsetof(struct wlfw_request_mem_ind_msg_v01, - size), + mem_seg_len), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_NUM_MEM_SEG_V01, + .elem_size = sizeof(struct wlfw_mem_seg_s_v01), + .is_array = VAR_LEN_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct wlfw_request_mem_ind_msg_v01, + mem_seg), + .ei_array = wlfw_mem_seg_s_v01_ei, }, { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; struct elem_info wlfw_respond_mem_req_msg_v01_ei[] = { { - .data_type = QMI_UNSIGNED_8_BYTE, + .data_type = QMI_DATA_LEN, .elem_len = 1, - .elem_size = sizeof(u64), + .elem_size = sizeof(u8), .is_array = NO_ARRAY, .tlv_type = 0x01, .offset = offsetof(struct wlfw_respond_mem_req_msg_v01, - addr), + mem_seg_len), }, { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .is_array = NO_ARRAY, - .tlv_type = 0x02, + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_NUM_MEM_SEG_V01, + .elem_size = sizeof(struct wlfw_mem_seg_resp_s_v01), + .is_array = VAR_LEN_ARRAY, + .tlv_type = 0x01, .offset = offsetof(struct wlfw_respond_mem_req_msg_v01, - size), + mem_seg), + .ei_array = wlfw_mem_seg_resp_s_v01_ei, }, { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1945,7 +2323,7 @@ struct elem_info wlfw_respond_mem_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -1953,15 +2331,15 @@ struct elem_info wlfw_fw_mem_ready_ind_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -struct elem_info wlfw_cold_boot_cal_done_ind_msg_v01_ei[] = { +struct elem_info wlfw_fw_init_done_ind_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -2041,7 +2419,7 @@ struct elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -2049,7 +2427,7 @@ struct elem_info wlfw_rejuvenate_ack_req_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -2068,7 +2446,7 @@ struct elem_info wlfw_rejuvenate_ack_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -2096,7 +2474,7 @@ struct elem_info wlfw_dynamic_feature_mask_req_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -2155,7 +2533,7 @@ struct elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -2181,7 +2559,7 @@ struct elem_info wlfw_m3_info_req_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -2199,7 +2577,7 @@ struct elem_info wlfw_m3_info_resp_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; @@ -2216,6 +2594,14 @@ struct elem_info wlfw_xo_cal_ind_msg_v01_ei[] = { { .data_type = QMI_EOTI, .is_array = NO_ARRAY, - .is_array = QMI_COMMON_TLV_TYPE, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct elem_info wlfw_cal_done_ind_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .is_array = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, }, }; diff --git a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h index 9b56eb0c02fb..00a873d11d14 100644 --- a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h +++ b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, 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 @@ -23,10 +23,12 @@ #define QMI_WLFW_BDF_DOWNLOAD_REQ_V01 0x0025 #define QMI_WLFW_FW_MEM_READY_IND_V01 0x0037 #define QMI_WLFW_INITIATE_CAL_UPDATE_IND_V01 0x002A +#define QMI_WLFW_CAL_DONE_IND_V01 0x003E #define QMI_WLFW_HOST_CAP_REQ_V01 0x0034 #define QMI_WLFW_DYNAMIC_FEATURE_MASK_RESP_V01 0x003B #define QMI_WLFW_M3_INFO_REQ_V01 0x003C #define QMI_WLFW_CAP_REQ_V01 0x0024 +#define QMI_WLFW_FW_INIT_DONE_IND_V01 0x0038 #define QMI_WLFW_CAL_REPORT_REQ_V01 0x0026 #define QMI_WLFW_M3_INFO_RESP_V01 0x003C #define QMI_WLFW_CAL_UPDATE_RESP_V01 0x0029 @@ -42,7 +44,6 @@ #define QMI_WLFW_WLAN_MODE_REQ_V01 0x0022 #define QMI_WLFW_IND_REGISTER_REQ_V01 0x0020 #define QMI_WLFW_WLAN_CFG_RESP_V01 0x0023 -#define QMI_WLFW_COLD_BOOT_CAL_DONE_IND_V01 0x0038 #define QMI_WLFW_REQUEST_MEM_IND_V01 0x0035 #define QMI_WLFW_REJUVENATE_IND_V01 0x0039 #define QMI_WLFW_DYNAMIC_FEATURE_MASK_REQ_V01 0x003B @@ -72,13 +73,16 @@ #define QMI_WLFW_IND_REGISTER_RESP_V01 0x0020 #define QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01 2 +#define QMI_WLFW_MAX_NUM_MEM_SEG_V01 32 #define QMI_WLFW_MAX_NUM_CAL_V01 5 #define QMI_WLFW_MAX_DATA_SIZE_V01 6144 #define QMI_WLFW_FUNCTION_NAME_LEN_V01 128 #define QMI_WLFW_MAX_NUM_CE_V01 12 #define QMI_WLFW_MAX_TIMESTAMP_LEN_V01 32 #define QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01 6144 +#define QMI_WLFW_MAX_NUM_GPIO_V01 32 #define QMI_WLFW_MAX_BUILD_ID_LEN_V01 128 +#define QMI_WLFW_MAX_NUM_MEM_CFG_V01 2 #define QMI_WLFW_MAX_STR_LEN_V01 16 #define QMI_WLFW_MAX_NUM_SHADOW_REG_V01 24 #define QMI_WLFW_MAC_ADDR_SIZE_V01 6 @@ -117,6 +121,17 @@ enum wlfw_pipedir_enum_v01 { WLFW_PIPEDIR_ENUM_MAX_VAL_V01 = INT_MAX, }; +enum wlfw_mem_type_enum_v01 { + WLFW_MEM_TYPE_ENUM_MIN_VAL_V01 = INT_MIN, + QMI_WLFW_MEM_TYPE_MSA_V01 = 0, + QMI_WLFW_MEM_TYPE_DDR_V01 = 1, + QMI_WLFW_MEM_BDF_V01 = 2, + QMI_WLFW_MEM_M3_V01 = 3, + QMI_WLFW_MEM_CAL_V01 = 4, + QMI_WLFW_MEM_DPD_V01 = 5, + WLFW_MEM_TYPE_ENUM_MAX_VAL_V01 = INT_MAX, +}; + #define QMI_WLFW_CE_ATTR_FLAGS_V01 ((u32)0x00) #define QMI_WLFW_CE_ATTR_NO_SNOOP_V01 ((u32)0x01) #define QMI_WLFW_CE_ATTR_BYTE_SWAP_DATA_V01 ((u32)0x02) @@ -128,6 +143,7 @@ enum wlfw_pipedir_enum_v01 { #define QMI_WLFW_FW_READY_V01 ((u64)0x02ULL) #define QMI_WLFW_MSA_READY_V01 ((u64)0x04ULL) #define QMI_WLFW_FW_MEM_READY_V01 ((u64)0x08ULL) +#define QMI_WLFW_FW_INIT_DONE_V01 ((u64)0x10ULL) #define QMI_WLFW_FW_REJUVENATE_V01 ((u64)0x01ULL) @@ -160,6 +176,26 @@ struct wlfw_memory_region_info_s_v01 { u8 secure_flag; }; +struct wlfw_mem_cfg_s_v01 { + u64 offset; + u32 size; + u8 secure_flag; +}; + +struct wlfw_mem_seg_s_v01 { + u32 size; + enum wlfw_mem_type_enum_v01 type; + u32 mem_cfg_len; + struct wlfw_mem_cfg_s_v01 mem_cfg[QMI_WLFW_MAX_NUM_MEM_CFG_V01]; +}; + +struct wlfw_mem_seg_resp_s_v01 { + u64 addr; + u32 size; + enum wlfw_mem_type_enum_v01 type; + u8 restore; +}; + struct wlfw_rf_chip_info_s_v01 { u32 chip_id; u32 chip_family; @@ -195,13 +231,17 @@ struct wlfw_ind_register_req_msg_v01 { u8 request_mem_enable; u8 fw_mem_ready_enable_valid; u8 fw_mem_ready_enable; - u8 cold_boot_cal_done_enable_valid; - u8 cold_boot_cal_done_enable; + u8 fw_init_done_enable_valid; + u8 fw_init_done_enable; u8 rejuvenate_enable_valid; u32 rejuvenate_enable; + u8 xo_cal_enable_valid; + u8 xo_cal_enable; + u8 cal_done_enable_valid; + u8 cal_done_enable; }; -#define WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 46 +#define WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 54 extern struct elem_info wlfw_ind_register_req_msg_v01_ei[]; struct wlfw_ind_register_resp_msg_v01 { @@ -533,13 +573,36 @@ struct wlfw_mac_addr_resp_msg_v01 { extern struct elem_info wlfw_mac_addr_resp_msg_v01_ei[]; struct wlfw_host_cap_req_msg_v01 { - u8 daemon_support_valid; - u8 daemon_support; + u8 num_clients_valid; + u32 num_clients; u8 wake_msi_valid; u32 wake_msi; -}; - -#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 11 + u8 gpios_valid; + u32 gpios_len; + u32 gpios[QMI_WLFW_MAX_NUM_GPIO_V01]; + u8 nm_modem_valid; + u8 nm_modem; + u8 bdf_support_valid; + u8 bdf_support; + u8 bdf_cache_support_valid; + u8 bdf_cache_support; + u8 m3_support_valid; + u8 m3_support; + u8 m3_cache_support_valid; + u8 m3_cache_support; + u8 cal_filesys_support_valid; + u8 cal_filesys_support; + u8 cal_cache_support_valid; + u8 cal_cache_support; + u8 cal_done_valid; + u8 cal_done; + u8 mem_bucket_valid; + u32 mem_bucket; + u8 mem_cfg_mode_valid; + u8 mem_cfg_mode; +}; + +#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 189 extern struct elem_info wlfw_host_cap_req_msg_v01_ei[]; struct wlfw_host_cap_resp_msg_v01 { @@ -550,18 +613,19 @@ struct wlfw_host_cap_resp_msg_v01 { extern struct elem_info wlfw_host_cap_resp_msg_v01_ei[]; struct wlfw_request_mem_ind_msg_v01 { - u32 size; + u32 mem_seg_len; + struct wlfw_mem_seg_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01]; }; -#define WLFW_REQUEST_MEM_IND_MSG_V01_MAX_MSG_LEN 7 +#define WLFW_REQUEST_MEM_IND_MSG_V01_MAX_MSG_LEN 1124 extern struct elem_info wlfw_request_mem_ind_msg_v01_ei[]; struct wlfw_respond_mem_req_msg_v01 { - u64 addr; - u32 size; + u32 mem_seg_len; + struct wlfw_mem_seg_resp_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01]; }; -#define WLFW_RESPOND_MEM_REQ_MSG_V01_MAX_MSG_LEN 18 +#define WLFW_RESPOND_MEM_REQ_MSG_V01_MAX_MSG_LEN 548 extern struct elem_info wlfw_respond_mem_req_msg_v01_ei[]; struct wlfw_respond_mem_resp_msg_v01 { @@ -578,12 +642,12 @@ struct wlfw_fw_mem_ready_ind_msg_v01 { #define WLFW_FW_MEM_READY_IND_MSG_V01_MAX_MSG_LEN 0 extern struct elem_info wlfw_fw_mem_ready_ind_msg_v01_ei[]; -struct wlfw_cold_boot_cal_done_ind_msg_v01 { +struct wlfw_fw_init_done_ind_msg_v01 { char placeholder; }; -#define WLFW_COLD_BOOT_CAL_DONE_IND_MSG_V01_MAX_MSG_LEN 0 -extern struct elem_info wlfw_cold_boot_cal_done_ind_msg_v01_ei[]; +#define WLFW_FW_INIT_DONE_IND_MSG_V01_MAX_MSG_LEN 0 +extern struct elem_info wlfw_fw_init_done_ind_msg_v01_ei[]; struct wlfw_rejuvenate_ind_msg_v01 { u8 cause_for_rejuvenation_valid; @@ -654,4 +718,11 @@ struct wlfw_xo_cal_ind_msg_v01 { #define WLFW_XO_CAL_IND_MSG_V01_MAX_MSG_LEN 4 extern struct elem_info wlfw_xo_cal_ind_msg_v01_ei[]; +struct wlfw_cal_done_ind_msg_v01 { + char placeholder; +}; + +#define WLFW_CAL_DONE_IND_MSG_V01_MAX_MSG_LEN 0 +extern struct elem_info wlfw_cal_done_ind_msg_v01_ei[]; + #endif diff --git a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c index 039a8b6a50b5..3defc03c2571 100644 --- a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c @@ -1432,6 +1432,8 @@ static int ipa_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /* Extended IOCTLs */ case RMNET_IOCTL_EXTENDED: + if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) + return -EPERM; IPAWANDBG("get ioctl: RMNET_IOCTL_EXTENDED\n"); if (copy_from_user(&extend_ioctl_data, (u8 *)ifr->ifr_ifru.ifru_data, @@ -2869,7 +2871,7 @@ int rmnet_ipa_query_tethering_stats_modem( if (reset) { req->reset_stats_valid = true; req->reset_stats = true; - IPAWANERR("reset the pipe stats\n"); + IPAWANDBG("reset the pipe stats\n"); } else { /* print tethered-client enum */ IPAWANDBG("Tethered-client enum(%d)\n", data->ipa_client); diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c index c9e5a46c08f0..900f5077e901 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c @@ -1566,6 +1566,8 @@ static int ipa3_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /* Extended IOCTLs */ case RMNET_IOCTL_EXTENDED: + if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) + return -EPERM; IPAWANDBG("get ioctl: RMNET_IOCTL_EXTENDED\n"); if (copy_from_user(&extend_ioctl_data, (u8 *)ifr->ifr_ifru.ifru_data, @@ -3013,7 +3015,7 @@ static int rmnet_ipa3_query_tethering_stats_modem( if (reset) { req->reset_stats_valid = true; req->reset_stats = true; - IPAWANERR("reset the pipe stats\n"); + IPAWANDBG("reset the pipe stats\n"); } else { /* print tethered-client enum */ IPAWANDBG("Tethered-client enum(%d)\n", data->ipa_client); diff --git a/drivers/soc/qcom/hab/hab.h b/drivers/soc/qcom/hab/hab.h index ce4c94fa75c9..ffb0637055d4 100644 --- a/drivers/soc/qcom/hab/hab.h +++ b/drivers/soc/qcom/hab/hab.h @@ -147,7 +147,8 @@ struct hab_header { (((vcid) & HAB_VCID_ID_MASK) >> HAB_VCID_ID_SHIFT) -#define HAB_HEADER_SET_SESSION_ID(header, sid) ((header).session_id = (sid)) +#define HAB_HEADER_SET_SESSION_ID(header, sid) \ + ((header).session_id = (sid)) #define HAB_HEADER_SET_SIZE(header, size) \ ((header).id_type_size = ((header).id_type_size & \ @@ -281,8 +282,8 @@ struct uhab_context { }; /* - * array to describe the VM and its MMID configuration as what is connected to - * so this is describing a pchan's remote side + * array to describe the VM and its MMID configuration as + * what is connected to so this is describing a pchan's remote side */ struct vmid_mmid_desc { int vmid; /* remote vmid */ @@ -341,8 +342,9 @@ struct virtual_channel { }; /* - * Struct shared between local and remote, contents are composed by exporter, - * the importer only writes to pdata and local (exporter) domID + * Struct shared between local and remote, contents + * are composed by exporter, the importer only writes + * to pdata and local (exporter) domID */ struct export_desc { uint32_t export_id; @@ -410,16 +412,10 @@ int habmem_hyp_revoke(void *expdata, uint32_t count); void *habmem_imp_hyp_open(void); void habmem_imp_hyp_close(void *priv, int kernel); -long habmem_imp_hyp_map(void *priv, void *impdata, uint32_t count, - uint32_t remotedom, - uint64_t *index, - void **pkva, - int kernel, - uint32_t userflags); +int habmem_imp_hyp_map(void *imp_ctx, struct hab_import *param, + struct export_desc *exp, int kernel); -long habmm_imp_hyp_unmap(void *priv, uint64_t index, - uint32_t count, - int kernel); +int habmm_imp_hyp_unmap(void *imp_ctx, struct export_desc *exp); int habmem_imp_hyp_mmap(struct file *flip, struct vm_area_struct *vma); diff --git a/drivers/soc/qcom/hab/hab_mem_linux.c b/drivers/soc/qcom/hab/hab_mem_linux.c index ecc3f52a6662..a779067ee4c4 100644 --- a/drivers/soc/qcom/hab/hab_mem_linux.c +++ b/drivers/soc/qcom/hab/hab_mem_linux.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, 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 @@ -29,6 +29,9 @@ struct pages_list { uint32_t userflags; struct file *filp_owner; struct file *filp_mapper; + struct dma_buf *dmabuf; + int32_t export_id; + int32_t vcid; }; struct importer_context { @@ -58,7 +61,7 @@ static int match_file(const void *p, struct file *file, unsigned int fd) } -static int habmem_get_dma_pages(unsigned long address, +static int habmem_get_dma_pages_from_va(unsigned long address, int page_count, struct page **pages) { @@ -142,6 +145,56 @@ err: return rc; } +static int habmem_get_dma_pages_from_fd(int32_t fd, + int page_count, + struct page **pages) +{ + struct dma_buf *dmabuf = NULL; + struct scatterlist *s; + struct sg_table *sg_table = NULL; + struct dma_buf_attachment *attach = NULL; + struct page *page; + int i, j, rc = 0; + + dmabuf = dma_buf_get(fd); + if (IS_ERR(dmabuf)) + return PTR_ERR(dmabuf); + + attach = dma_buf_attach(dmabuf, hab_driver.dev); + if (IS_ERR_OR_NULL(attach)) { + pr_err("dma_buf_attach failed\n"); + goto err; + } + + sg_table = dma_buf_map_attachment(attach, DMA_TO_DEVICE); + + if (IS_ERR_OR_NULL(sg_table)) { + pr_err("dma_buf_map_attachment failed\n"); + goto err; + } + + for_each_sg(sg_table->sgl, s, sg_table->nents, i) { + page = sg_page(s); + pr_debug("sgl length %d\n", s->length); + + for (j = 0; j < (s->length >> PAGE_SHIFT); j++) { + pages[rc] = nth_page(page, j); + rc++; + if (WARN_ON(rc >= page_count)) + break; + } + } + +err: + if (!IS_ERR_OR_NULL(sg_table)) + dma_buf_unmap_attachment(attach, sg_table, DMA_TO_DEVICE); + if (!IS_ERR_OR_NULL(attach)) + dma_buf_detach(dmabuf, attach); + if (!IS_ERR_OR_NULL(dmabuf)) + dma_buf_put(dmabuf); + return rc; +} + /* * exporter - grant & revoke * degenerate sharabled page list based on CPU friendly virtual "address". @@ -165,7 +218,11 @@ int habmem_hyp_grant_user(unsigned long address, down_read(¤t->mm->mmap_sem); if (HABMM_EXP_MEM_TYPE_DMA & flags) { - ret = habmem_get_dma_pages(address, + ret = habmem_get_dma_pages_from_va(address, + page_count, + pages); + } else if (HABMM_EXPIMP_FLAGS_FD & flags) { + ret = habmem_get_dma_pages_from_fd(address, page_count, pages); } else { @@ -260,30 +317,156 @@ void habmem_imp_hyp_close(void *imp_ctx, int kernel) kfree(priv); } -/* - * setup pages, be ready for the following mmap call - * index is output to refer to this imported buffer described by the import data - */ -long habmem_imp_hyp_map(void *imp_ctx, - void *impdata, - uint32_t count, - uint32_t remotedom, - uint64_t *index, - void **pkva, - int kernel, - uint32_t userflags) +static struct sg_table *hab_mem_map_dma_buf( + struct dma_buf_attachment *attachment, + enum dma_data_direction direction) +{ + struct dma_buf *dmabuf = attachment->dmabuf; + struct pages_list *pglist = dmabuf->priv; + struct sg_table *sgt; + struct scatterlist *sg; + int i; + int ret = 0; + struct page **pages = pglist->pages; + + sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!sgt) + return ERR_PTR(-ENOMEM); + + ret = sg_alloc_table(sgt, pglist->npages, GFP_KERNEL); + if (ret) { + kfree(sgt); + return ERR_PTR(-ENOMEM); + } + + for_each_sg(sgt->sgl, sg, pglist->npages, i) { + sg_set_page(sg, pages[i], PAGE_SIZE, 0); + } + + return sgt; +} + + +static void hab_mem_unmap_dma_buf(struct dma_buf_attachment *attachment, + struct sg_table *sgt, + enum dma_data_direction direction) +{ + sg_free_table(sgt); + kfree(sgt); +} + +static int hab_map_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct page *page; + struct pages_list *pglist; + + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + + /* PHY address */ + unsigned long fault_offset = + (unsigned long)vmf->virtual_address - vma->vm_start + offset; + unsigned long fault_index = fault_offset>>PAGE_SHIFT; + int page_idx; + + if (vma == NULL) + return VM_FAULT_SIGBUS; + + pglist = vma->vm_private_data; + + page_idx = fault_index - pglist->index; + if (page_idx < 0 || page_idx >= pglist->npages) { + pr_err("Out of page array! page_idx %d, pg cnt %ld", + page_idx, pglist->npages); + return VM_FAULT_SIGBUS; + } + + page = pglist->pages[page_idx]; + get_page(page); + vmf->page = page; + return 0; +} + +static void hab_map_open(struct vm_area_struct *vma) +{ +} + +static void hab_map_close(struct vm_area_struct *vma) +{ +} + +static const struct vm_operations_struct habmem_vm_ops = { + .fault = hab_map_fault, + .open = hab_map_open, + .close = hab_map_close, +}; + +static int hab_mem_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) +{ + struct pages_list *pglist = dmabuf->priv; + uint32_t obj_size = pglist->npages << PAGE_SHIFT; + + if (vma == NULL) + return VM_FAULT_SIGBUS; + + /* Check for valid size. */ + if (obj_size < vma->vm_end - vma->vm_start) + return -EINVAL; + + vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP; + vma->vm_ops = &habmem_vm_ops; + vma->vm_private_data = pglist; + vma->vm_flags |= VM_MIXEDMAP; + + return 0; +} + +static void hab_mem_dma_buf_release(struct dma_buf *dmabuf) +{ +} + +static void *hab_mem_dma_buf_kmap(struct dma_buf *dmabuf, + unsigned long offset) +{ + return NULL; +} + +static void hab_mem_dma_buf_kunmap(struct dma_buf *dmabuf, + unsigned long offset, + void *ptr) +{ +} + +static struct dma_buf_ops dma_buf_ops = { + .map_dma_buf = hab_mem_map_dma_buf, + .unmap_dma_buf = hab_mem_unmap_dma_buf, + .mmap = hab_mem_mmap, + .release = hab_mem_dma_buf_release, + .kmap_atomic = hab_mem_dma_buf_kmap, + .kunmap_atomic = hab_mem_dma_buf_kunmap, + .kmap = hab_mem_dma_buf_kmap, + .kunmap = hab_mem_dma_buf_kunmap, +}; + +static int habmem_imp_hyp_map_fd(void *imp_ctx, + struct export_desc *exp, + uint32_t userflags, + int32_t *pfd) { struct page **pages; - struct compressed_pfns *pfn_table = (struct compressed_pfns *)impdata; + struct compressed_pfns *pfn_table = + (struct compressed_pfns *)exp->payload; struct pages_list *pglist; struct importer_context *priv = imp_ctx; unsigned long pfn; int i, j, k = 0; + pgprot_t prot = PAGE_KERNEL; + int32_t fd; + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); if (!pfn_table || !priv) return -EINVAL; - pages = vmalloc(count * sizeof(struct page *)); + pages = vmalloc(exp->payload_count * sizeof(struct page *)); if (!pages) return -ENOMEM; @@ -303,145 +486,230 @@ long habmem_imp_hyp_map(void *imp_ctx, } pglist->pages = pages; - pglist->npages = count; - pglist->kernel = kernel; - pglist->index = page_to_phys(pages[0]) >> PAGE_SHIFT; + pglist->npages = exp->payload_count; + pglist->kernel = 0; + pglist->index = 0; pglist->refcntk = pglist->refcntu = 0; pglist->userflags = userflags; + pglist->export_id = exp->export_id; + pglist->vcid = exp->vcid_remote; + + if (!(userflags & HABMM_IMPORT_FLAGS_CACHED)) + prot = pgprot_writecombine(prot); + + exp_info.ops = &dma_buf_ops; + exp_info.size = exp->payload_count << PAGE_SHIFT; + exp_info.flags = O_RDWR; + exp_info.priv = pglist; + pglist->dmabuf = dma_buf_export(&exp_info); + if (IS_ERR(pglist->dmabuf)) { + vfree(pages); + kfree(pglist); + return PTR_ERR(pglist->dmabuf); + } - *index = pglist->index << PAGE_SHIFT; - - if (kernel) { - pgprot_t prot = PAGE_KERNEL; - - if (!(userflags & HABMM_IMPORT_FLAGS_CACHED)) - prot = pgprot_writecombine(prot); - - pglist->kva = vmap(pglist->pages, pglist->npages, VM_MAP, prot); - if (pglist->kva == NULL) { - vfree(pages); - kfree(pglist); - pr_err("%ld pages vmap failed\n", pglist->npages); - return -ENOMEM; - } else { - pr_debug("%ld pages vmap pass, return %pK\n", - pglist->npages, pglist->kva); - } - - pglist->uva = NULL; - pglist->refcntk++; - *pkva = pglist->kva; - *index = (uint64_t)((uintptr_t)pglist->kva); - } else { - pglist->kva = NULL; + fd = dma_buf_fd(pglist->dmabuf, O_CLOEXEC); + if (fd < 0) { + dma_buf_put(pglist->dmabuf); + vfree(pages); + kfree(pglist); + return -EINVAL; } + pglist->refcntk++; + write_lock(&priv->implist_lock); list_add_tail(&pglist->list, &priv->imp_list); priv->cnt++; write_unlock(&priv->implist_lock); - pr_debug("index returned %llx\n", *index); + + *pfd = fd; return 0; } -/* the input index is PHY address shifted for uhab, and kva for khab */ -long habmm_imp_hyp_unmap(void *imp_ctx, - uint64_t index, - uint32_t count, - int kernel) +static int habmem_imp_hyp_map_kva(void *imp_ctx, + struct export_desc *exp, + uint32_t userflags, + void **pkva) { + struct page **pages; + struct compressed_pfns *pfn_table = + (struct compressed_pfns *)exp->payload; + struct pages_list *pglist; struct importer_context *priv = imp_ctx; - struct pages_list *pglist, *tmp; - int found = 0; - uint64_t pg_index = index >> PAGE_SHIFT; - - write_lock(&priv->implist_lock); - list_for_each_entry_safe(pglist, tmp, &priv->imp_list, list) { - pr_debug("node pglist %pK, kernel %d, pg_index %llx\n", - pglist, pglist->kernel, pg_index); + unsigned long pfn; + int i, j, k = 0; + pgprot_t prot = PAGE_KERNEL; - if (kernel) { - if (pglist->kva == (void *)((uintptr_t)index)) - found = 1; - } else { - if (pglist->index == pg_index) - found = 1; - } + if (!pfn_table || !priv) + return -EINVAL; + pages = vmalloc(exp->payload_count * sizeof(struct page *)); + if (!pages) + return -ENOMEM; + pglist = kzalloc(sizeof(*pglist), GFP_KERNEL); + if (!pglist) { + vfree(pages); + return -ENOMEM; + } - if (found) { - list_del(&pglist->list); - priv->cnt--; - break; + pfn = pfn_table->first_pfn; + for (i = 0; i < pfn_table->nregions; i++) { + for (j = 0; j < pfn_table->region[i].size; j++) { + pages[k] = pfn_to_page(pfn+j); + k++; } + pfn += pfn_table->region[i].size + pfn_table->region[i].space; } - write_unlock(&priv->implist_lock); - if (!found) { - pr_err("failed to find export id on index %llx\n", index); - return -EINVAL; + pglist->pages = pages; + pglist->npages = exp->payload_count; + pglist->kernel = 1; + pglist->refcntk = pglist->refcntu = 0; + pglist->userflags = userflags; + pglist->export_id = exp->export_id; + pglist->vcid = exp->vcid_remote; + + if (!(userflags & HABMM_IMPORT_FLAGS_CACHED)) + prot = pgprot_writecombine(prot); + + pglist->kva = vmap(pglist->pages, pglist->npages, VM_MAP, prot); + if (pglist->kva == NULL) { + vfree(pages); + kfree(pglist); + pr_err("%ld pages vmap failed\n", pglist->npages); + return -ENOMEM; } - pr_debug("detach pglist %pK, index %llx, kernel %d, list cnt %d\n", - pglist, pglist->index, pglist->kernel, priv->cnt); + pr_debug("%ld pages vmap pass, return %p\n", + pglist->npages, pglist->kva); - if (kernel) - if (pglist->kva) - vunmap(pglist->kva); + pglist->refcntk++; - vfree(pglist->pages); - kfree(pglist); + write_lock(&priv->implist_lock); + list_add_tail(&pglist->list, &priv->imp_list); + priv->cnt++; + write_unlock(&priv->implist_lock); + + *pkva = pglist->kva; return 0; } -static int hab_map_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +static int habmem_imp_hyp_map_uva(void *imp_ctx, + struct export_desc *exp, + uint32_t userflags, + uint64_t *index) { - struct page *page; + struct page **pages; + struct compressed_pfns *pfn_table = + (struct compressed_pfns *)exp->payload; struct pages_list *pglist; + struct importer_context *priv = imp_ctx; + unsigned long pfn; + int i, j, k = 0; - unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; - - /* PHY address */ - unsigned long fault_offset = - (unsigned long)vmf->virtual_address - vma->vm_start + offset; - unsigned long fault_index = fault_offset>>PAGE_SHIFT; - int page_idx; + if (!pfn_table || !priv) + return -EINVAL; - if (vma == NULL) - return VM_FAULT_SIGBUS; + pages = vmalloc(exp->payload_count * sizeof(struct page *)); + if (!pages) + return -ENOMEM; - pglist = vma->vm_private_data; + pglist = kzalloc(sizeof(*pglist), GFP_KERNEL); + if (!pglist) { + vfree(pages); + return -ENOMEM; + } - page_idx = fault_index - pglist->index; - if (page_idx < 0 || page_idx >= pglist->npages) { - pr_err("Out of page array. page_idx %d, pg cnt %ld", - page_idx, pglist->npages); - return VM_FAULT_SIGBUS; + pfn = pfn_table->first_pfn; + for (i = 0; i < pfn_table->nregions; i++) { + for (j = 0; j < pfn_table->region[i].size; j++) { + pages[k] = pfn_to_page(pfn+j); + k++; + } + pfn += pfn_table->region[i].size + pfn_table->region[i].space; } - pr_debug("Fault page index %d\n", page_idx); + pglist->pages = pages; + pglist->npages = exp->payload_count; + pglist->index = page_to_phys(pages[0]) >> PAGE_SHIFT; + pglist->refcntk = pglist->refcntu = 0; + pglist->userflags = userflags; + pglist->export_id = exp->export_id; + pglist->vcid = exp->vcid_remote; + + write_lock(&priv->implist_lock); + list_add_tail(&pglist->list, &priv->imp_list); + priv->cnt++; + write_unlock(&priv->implist_lock); + + *index = pglist->index << PAGE_SHIFT; - page = pglist->pages[page_idx]; - get_page(page); - vmf->page = page; return 0; } -static void hab_map_open(struct vm_area_struct *vma) +int habmem_imp_hyp_map(void *imp_ctx, struct hab_import *param, + struct export_desc *exp, int kernel) { + int ret = 0; + + if (kernel) + ret = habmem_imp_hyp_map_kva(imp_ctx, exp, + param->flags, + (void **)¶m->kva); + else if (param->flags & HABMM_EXPIMP_FLAGS_FD) + ret = habmem_imp_hyp_map_fd(imp_ctx, exp, + param->flags, + (int32_t *)¶m->kva); + else + ret = habmem_imp_hyp_map_uva(imp_ctx, exp, + param->flags, + ¶m->index); + + return ret; } -static void hab_map_close(struct vm_area_struct *vma) +int habmm_imp_hyp_unmap(void *imp_ctx, struct export_desc *exp) { -} + struct importer_context *priv = imp_ctx; + struct pages_list *pglist, *tmp; + int found = 0; -static const struct vm_operations_struct habmem_vm_ops = { + write_lock(&priv->implist_lock); + list_for_each_entry_safe(pglist, tmp, &priv->imp_list, list) { + if (pglist->export_id == exp->export_id && + pglist->vcid == exp->vcid_remote) { + found = 1; + } - .fault = hab_map_fault, - .open = hab_map_open, - .close = hab_map_close, -}; + if (found) { + list_del(&pglist->list); + priv->cnt--; + break; + } + } + write_unlock(&priv->implist_lock); + + if (!found) { + pr_err("failed to find export id %u\n", exp->export_id); + return -EINVAL; + } + + pr_debug("detach pglist %p, kernel %d, list cnt %d\n", + pglist, pglist->kernel, priv->cnt); + + if (pglist->kva) + vunmap(pglist->kva); + + if (pglist->dmabuf) + dma_buf_put(pglist->dmabuf); + + vfree(pglist->pages); + kfree(pglist); + + return 0; +} int habmem_imp_hyp_mmap(struct file *filp, struct vm_area_struct *vma) { diff --git a/drivers/soc/qcom/hab/hab_mimex.c b/drivers/soc/qcom/hab/hab_mimex.c index 67601590908e..00fbeabed4bb 100644 --- a/drivers/soc/qcom/hab/hab_mimex.c +++ b/drivers/soc/qcom/hab/hab_mimex.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, 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 @@ -345,25 +345,20 @@ int hab_mem_import(struct uhab_context *ctx, exp->export_id, exp->payload_count, exp->domid_local, *((uint32_t *)exp->payload)); - ret = habmem_imp_hyp_map(ctx->import_ctx, - exp->payload, - exp->payload_count, - exp->domid_local, - &exp->import_index, - &exp->kva, - kernel, - param->flags); + ret = habmem_imp_hyp_map(ctx->import_ctx, param, exp, kernel); + if (ret) { pr_err("Import fail ret:%d pcnt:%d rem:%d 1st_ref:0x%X\n", ret, exp->payload_count, exp->domid_local, *((uint32_t *)exp->payload)); return ret; } - pr_debug("import index %llx, kva %llx, kernel %d\n", - exp->import_index, param->kva, kernel); - param->index = exp->import_index; - param->kva = (uint64_t)exp->kva; + exp->import_index = param->index; + exp->kva = kernel ? (void *)param->kva : NULL; + + pr_debug("import index %llx, kva or fd %llx, kernel %d\n", + exp->import_index, param->kva, kernel); return ret; } @@ -396,13 +391,10 @@ int hab_mem_unimport(struct uhab_context *ctx, if (!found) ret = -EINVAL; else { - ret = habmm_imp_hyp_unmap(ctx->import_ctx, - exp->import_index, - exp->payload_count, - kernel); + ret = habmm_imp_hyp_unmap(ctx->import_ctx, exp); if (ret) { - pr_err("unmap fail id:%d pcnt:%d kernel:%d\n", - exp->export_id, exp->payload_count, kernel); + pr_err("unmap fail id:%d pcnt:%d vcid:%d\n", + exp->export_id, exp->payload_count, exp->vcid_remote); } param->kva = (uint64_t)exp->kva; kfree(exp); diff --git a/drivers/soc/qcom/hab/hab_vchan.c b/drivers/soc/qcom/hab/hab_vchan.c index 140d75656353..2db4db8f321b 100644 --- a/drivers/soc/qcom/hab/hab_vchan.c +++ b/drivers/soc/qcom/hab/hab_vchan.c @@ -110,10 +110,7 @@ hab_vchan_free(struct kref *ref) } spin_unlock_bh(&ctx->imp_lock); if (found) { - habmm_imp_hyp_unmap(ctx->import_ctx, - exp->import_index, - exp->payload_count, - ctx->kernel); + habmm_imp_hyp_unmap(ctx->import_ctx, exp); ctx->import_total--; kfree(exp); } diff --git a/drivers/soc/qcom/msm_performance.c b/drivers/soc/qcom/msm_performance.c index 1046af031838..1857d369bc94 100644 --- a/drivers/soc/qcom/msm_performance.c +++ b/drivers/soc/qcom/msm_performance.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2018, 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 @@ -2379,6 +2379,7 @@ end: static void __ref try_hotplug(struct cluster *data) { unsigned int i; + struct device *dev; if (!clusters_inited) return; @@ -2405,7 +2406,8 @@ static void __ref try_hotplug(struct cluster *data) pr_debug("msm_perf: Offlining CPU%d\n", i); cpumask_set_cpu(i, data->offlined_cpus); lock_device_hotplug(); - if (device_offline(get_cpu_device(i))) { + dev = get_cpu_device(i); + if (!dev || device_offline(dev)) { cpumask_clear_cpu(i, data->offlined_cpus); pr_debug("msm_perf: Offlining CPU%d failed\n", i); @@ -2423,7 +2425,8 @@ static void __ref try_hotplug(struct cluster *data) continue; pr_debug("msm_perf: Onlining CPU%d\n", i); lock_device_hotplug(); - if (device_online(get_cpu_device(i))) { + dev = get_cpu_device(i); + if (!dev || device_online(dev)) { pr_debug("msm_perf: Onlining CPU%d failed\n", i); unlock_device_hotplug(); @@ -2442,11 +2445,19 @@ static void __ref try_hotplug(struct cluster *data) static void __ref release_cluster_control(struct cpumask *off_cpus) { int cpu; + struct device *dev; for_each_cpu(cpu, off_cpus) { pr_debug("msm_perf: Release CPU %d\n", cpu); lock_device_hotplug(); - if (!device_online(get_cpu_device(cpu))) + dev = get_cpu_device(cpu); + if (!dev) { + pr_debug("msm_perf: Failed to get CPU%d\n", + cpu); + unlock_device_hotplug(); + continue; + } + if (!device_online(dev)) cpumask_clear_cpu(cpu, off_cpus); unlock_device_hotplug(); } diff --git a/drivers/soc/qcom/qdsp6v2/apr.c b/drivers/soc/qcom/qdsp6v2/apr.c index b1afd02b49bf..fefc348c0027 100644 --- a/drivers/soc/qcom/qdsp6v2/apr.c +++ b/drivers/soc/qcom/qdsp6v2/apr.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2010-2014, 2016 The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2014, 2016, 2018 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 @@ -209,6 +210,16 @@ static struct apr_svc_table svc_tbl_voice[] = { }, }; +static const struct apr_svc_table svc_tbl_sdsp[] = { + { + /* Micro Audio Service */ + .name = "MAS", + .idx = 0, + .id = APR_SVC_MAS, + .client_id = APR_CLIENT_AUDIO, + }, +}; + enum apr_subsys_state apr_get_modem_state(void) { return atomic_read(&q6.modem_state); @@ -444,6 +455,9 @@ struct apr_svc *apr_register(char *dest, char *svc_name, apr_fn svc_fn, */ can_open_channel = false; domain_id = APR_DOMAIN_MODEM; + } else if (!strcmp(dest, "SDSP")) { + domain_id = APR_DOMAIN_SDSP; + pr_debug("APR: SDSP DOMAIN_ID %d\n", domain_id); } else { pr_err("APR: wrong destination\n"); goto done; @@ -472,6 +486,8 @@ struct apr_svc *apr_register(char *dest, char *svc_name, apr_fn svc_fn, } } pr_debug("%s: modem Up\n", __func__); + } else if (dest_id == APR_DEST_DSPS) { + pr_debug("%s: Sensor DSP Up\n", __func__); } if (apr_get_svc(svc_name, domain_id, &client_id, &svc_idx, &svc_id)) { @@ -624,6 +640,8 @@ void apr_cb_func(void *buf, int len, void *priv) pr_err("APR: Wrong svc :%d\n", svc); return; } + } else if (hdr->src_domain == APR_DOMAIN_SDSP) { + clnt = APR_CLIENT_AUDIO; } else { pr_err("APR: Pkt from wrong source: %d\n", hdr->src_domain); return; @@ -700,6 +718,9 @@ int apr_get_svc(const char *svc_name, int domain_id, int *client_id, if ((domain_id == APR_DOMAIN_ADSP)) { tbl = (struct apr_svc_table *)&svc_tbl_qdsp6; size = ARRAY_SIZE(svc_tbl_qdsp6); + } else if (domain_id == APR_DOMAIN_SDSP) { + tbl = (struct apr_svc_table *)&svc_tbl_sdsp; + size = ARRAY_SIZE(svc_tbl_sdsp); } else { tbl = (struct apr_svc_table *)&svc_tbl_voice; size = ARRAY_SIZE(svc_tbl_voice); diff --git a/drivers/soc/qcom/qdsp6v2/apr_tal.c b/drivers/soc/qcom/qdsp6v2/apr_tal.c index 6cffe7be655a..3884667cc12c 100644 --- a/drivers/soc/qcom/qdsp6v2/apr_tal.c +++ b/drivers/soc/qcom/qdsp6v2/apr_tal.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2011, 2013-2014, 2016 The Linux Foundation. +/* Copyright (c) 2010-2011, 2013-2014, 2016, 2018 The Linux Foundation. * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -38,6 +38,14 @@ static char *svc_names[APR_DEST_MAX][APR_CLIENT_MAX] = { "apr_audio_svc", "apr_voice_svc", }, + { + "", + "", + }, + { + "apr_apps_sdsp", + "apr_apps_sdsp", + }, }; struct apr_svc_ch_dev apr_svc_ch[APR_DL_MAX][APR_DEST_MAX][APR_CLIENT_MAX]; @@ -162,7 +170,8 @@ struct apr_svc_ch_dev *apr_tal_open(uint32_t clnt, uint32_t dest, if ((clnt >= APR_CLIENT_MAX) || (dest >= APR_DEST_MAX) || (dl >= APR_DL_MAX)) { - pr_err("apr_tal: Invalid params\n"); + pr_err("apr_tal: Invalid params clnt %d dest %d dl %d\n", + clnt, dest, dl); return NULL; } @@ -184,10 +193,12 @@ struct apr_svc_ch_dev *apr_tal_open(uint32_t clnt, uint32_t dest, pr_debug("apr_tal:Wakeup done\n"); apr_svc_ch[dl][dest][clnt].dest_state = 0; } + rc = smd_named_open_on_edge(svc_names[dest][clnt], dest, - &apr_svc_ch[dl][dest][clnt].ch, - &apr_svc_ch[dl][dest][clnt], - apr_tal_notify); + &apr_svc_ch[dl][dest][clnt].ch, + &apr_svc_ch[dl][dest][clnt], + apr_tal_notify); + if (rc < 0) { pr_err("apr_tal: smd_open failed %s\n", svc_names[dest][clnt]); @@ -256,6 +267,12 @@ static int apr_smd_probe(struct platform_device *pdev) clnt = APR_CLIENT_AUDIO; apr_svc_ch[APR_DL_SMD][dest][clnt].dest_state = 1; wake_up(&apr_svc_ch[APR_DL_SMD][dest][clnt].dest); + } else if (pdev->id == APR_DEST_DSPS) { + pr_info("apr_tal:Sensor DSP Is Up\n"); + dest = APR_DEST_DSPS; + clnt = APR_CLIENT_AUDIO; + apr_svc_ch[APR_DL_SMD][dest][clnt].dest_state = 1; + wake_up(&apr_svc_ch[APR_DL_SMD][dest][clnt].dest); } else pr_err("apr_tal:Invalid Dest Id: %d\n", pdev->id); @@ -278,6 +295,14 @@ static struct platform_driver apr_modem_driver = { }, }; +static struct platform_driver apr_sdsp_driver = { + .probe = apr_smd_probe, + .driver = { + .name = "apr_apps_sdsp", + .owner = THIS_MODULE, + }, +}; + static int __init apr_tal_init(void) { int i, j, k; @@ -293,6 +318,7 @@ static int __init apr_tal_init(void) } platform_driver_register(&apr_q6_driver); platform_driver_register(&apr_modem_driver); + platform_driver_register(&apr_sdsp_driver); return 0; } device_initcall(apr_tal_init); diff --git a/drivers/soc/qcom/qdsp6v2/apr_v2.c b/drivers/soc/qcom/qdsp6v2/apr_v2.c index 037fb3327ef0..d42f2ff5912e 100644 --- a/drivers/soc/qcom/qdsp6v2/apr_v2.c +++ b/drivers/soc/qcom/qdsp6v2/apr_v2.c @@ -37,6 +37,8 @@ uint16_t apr_get_data_src(struct apr_hdr *hdr) return APR_DEST_MODEM; else if (hdr->src_domain == APR_DOMAIN_ADSP) return APR_DEST_QDSP6; + else if (hdr->src_domain == APR_DOMAIN_SDSP) + return APR_DEST_DSPS; else { pr_err("APR: Pkt from wrong source: %d\n", hdr->src_domain); return APR_DEST_MAX; /*RETURN INVALID VALUE*/ @@ -47,6 +49,8 @@ int apr_get_dest_id(char *dest) { if (!strcmp(dest, "ADSP")) return APR_DEST_QDSP6; + else if (!strcmp(dest, "SDSP")) + return APR_DEST_DSPS; else return APR_DEST_MODEM; } diff --git a/drivers/soc/qcom/qdsp6v2/apr_vm.c b/drivers/soc/qcom/qdsp6v2/apr_vm.c index 56592ac91e1b..bd555b6e6f3b 100644 --- a/drivers/soc/qcom/qdsp6v2/apr_vm.c +++ b/drivers/soc/qcom/qdsp6v2/apr_vm.c @@ -529,25 +529,23 @@ static int apr_vm_cb_thread(void *data) { uint32_t apr_rx_buf_len; struct aprv2_vm_ack_rx_pkt_available_t apr_ack; + unsigned long delay = jiffies + (HZ / 2); int status = 0; int ret = 0; while (1) { - apr_rx_buf_len = sizeof(apr_rx_buf); - ret = habmm_socket_recv(hab_handle_rx, - (void *)&apr_rx_buf, - &apr_rx_buf_len, - 0xFFFFFFFF, - 0); + do { + apr_rx_buf_len = sizeof(apr_rx_buf); + ret = habmm_socket_recv(hab_handle_rx, + (void *)&apr_rx_buf, + &apr_rx_buf_len, + 0xFFFFFFFF, + 0); + } while (time_before(jiffies, delay) && (ret == -EAGAIN) && + (apr_rx_buf_len == 0)); if (ret) { pr_err("%s: habmm_socket_recv failed %d\n", __func__, ret); - /* - * TODO: depends on the HAB error code, - * may need to implement - * a retry mechanism. - * break if recv failed ? - */ break; } diff --git a/drivers/soc/qcom/qdsp6v2/msm_audio_ion_vm.c b/drivers/soc/qcom/qdsp6v2/msm_audio_ion_vm.c index 7ef16ad5575b..15c3e7e42c6d 100644 --- a/drivers/soc/qcom/qdsp6v2/msm_audio_ion_vm.c +++ b/drivers/soc/qcom/qdsp6v2/msm_audio_ion_vm.c @@ -83,6 +83,7 @@ static int msm_audio_ion_smmu_map(struct ion_client *client, struct msm_audio_smmu_vm_map_cmd_rsp cmd_rsp; struct msm_audio_smmu_map_data *map_data = NULL; struct msm_audio_smmu_vm_map_cmd smmu_map_cmd; + unsigned long delay = jiffies + (HZ / 2); rc = ion_handle_get_size(client, handle, len); if (rc) { @@ -122,12 +123,15 @@ static int msm_audio_ion_smmu_map(struct ion_client *client, goto err; } - cmd_rsp_size = sizeof(cmd_rsp); - rc = habmm_socket_recv(msm_audio_ion_hab_handle, - (void *)&cmd_rsp, - &cmd_rsp_size, - 0xFFFFFFFF, - 0); + do { + cmd_rsp_size = sizeof(cmd_rsp); + rc = habmm_socket_recv(msm_audio_ion_hab_handle, + (void *)&cmd_rsp, + &cmd_rsp_size, + 0xFFFFFFFF, + 0); + } while (time_before(jiffies, delay) && (rc == -EAGAIN) && + (cmd_rsp_size == 0)); if (rc) { pr_err("%s: habmm_socket_recv failed %d\n", __func__, rc); @@ -181,6 +185,7 @@ static int msm_audio_ion_smmu_unmap(struct ion_client *client, struct msm_audio_smmu_vm_unmap_cmd_rsp cmd_rsp; struct msm_audio_smmu_map_data *map_data, *next; struct msm_audio_smmu_vm_unmap_cmd smmu_unmap_cmd; + unsigned long delay = jiffies + (HZ / 2); /* * Though list_for_each_entry_safe is delete safe, lock @@ -205,12 +210,15 @@ static int msm_audio_ion_smmu_unmap(struct ion_client *client, goto err; } - cmd_rsp_size = sizeof(cmd_rsp); - rc = habmm_socket_recv(msm_audio_ion_hab_handle, - (void *)&cmd_rsp, - &cmd_rsp_size, - 0xFFFFFFFF, - 0); + do { + cmd_rsp_size = sizeof(cmd_rsp); + rc = habmm_socket_recv(msm_audio_ion_hab_handle, + (void *)&cmd_rsp, + &cmd_rsp_size, + 0xFFFFFFFF, + 0); + } while (time_before(jiffies, delay) && + (rc == -EAGAIN) && (cmd_rsp_size == 0)); if (rc) { pr_err("%s: habmm_socket_recv failed %d\n", __func__, rc); diff --git a/drivers/soc/qcom/rpm_stats.c b/drivers/soc/qcom/rpm_stats.c index b54af9eae8ec..ed7493d063ae 100644 --- a/drivers/soc/qcom/rpm_stats.c +++ b/drivers/soc/qcom/rpm_stats.c @@ -430,7 +430,7 @@ static ssize_t rpmstats_show(struct kobject *kobj, prvdata); } - ret = snprintf(buf, prvdata->len, prvdata->buf); + ret = snprintf(buf, prvdata->len, "%s", prvdata->buf); iounmap(prvdata->reg_base); ioremap_fail: kfree(prvdata); diff --git a/drivers/thermal/msm-tsens.c b/drivers/thermal/msm-tsens.c index 5f955af4671a..db49c33264d5 100644 --- a/drivers/thermal/msm-tsens.c +++ b/drivers/thermal/msm-tsens.c @@ -89,6 +89,7 @@ #define TSENS_TM_CRITICAL_INT_EN BIT(2) #define TSENS_TM_UPPER_INT_EN BIT(1) #define TSENS_TM_LOWER_INT_EN BIT(0) +#define TSENS_TM_UPPER_LOWER_INT_DISABLE 0xffffffff #define TSENS_TM_UPPER_INT_MASK(n) (((n) & 0xffff0000) >> 16) #define TSENS_TM_LOWER_INT_MASK(n) ((n) & 0xffff) @@ -269,8 +270,8 @@ struct tsens_tm_device { uint32_t wd_bark_val; int tsens_irq; int tsens_critical_irq; - void *tsens_addr; - void *tsens_calib_addr; + void __iomem *tsens_addr; + void __iomem *tsens_calib_addr; int tsens_len; int calib_len; struct resource *res_tsens_mem; @@ -2079,6 +2080,7 @@ static int tsens_hw_init(struct tsens_tm_device *tmdev) void __iomem *sensor_int_mask_addr; unsigned int srot_val; int crit_mask; + void __iomem *int_mask_addr; if (!tmdev) { pr_err("Invalid tsens device\n"); @@ -2104,6 +2106,10 @@ static int tsens_hw_init(struct tsens_tm_device *tmdev) /*Update critical cycle monitoring*/ mb(); } + int_mask_addr = TSENS_TM_UPPER_LOWER_INT_MASK + (tmdev->tsens_addr); + writel_relaxed(TSENS_TM_UPPER_LOWER_INT_DISABLE, + int_mask_addr); writel_relaxed(TSENS_TM_CRITICAL_INT_EN | TSENS_TM_UPPER_INT_EN | TSENS_TM_LOWER_INT_EN, TSENS_TM_INT_EN(tmdev->tsens_addr)); diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 2cd600a58fd7..3f59a2f8b84f 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -3487,6 +3487,7 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on) if (on) { dev_dbg(mdwc->dev, "%s: turn on host\n", __func__); + pm_runtime_get_sync(mdwc->dev); mdwc->hs_phy->flags |= PHY_HOST_MODE; if (dwc->maximum_speed == USB_SPEED_SUPER) { mdwc->ss_phy->flags |= PHY_HOST_MODE; @@ -3495,7 +3496,6 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on) } usb_phy_notify_connect(mdwc->hs_phy, USB_SPEED_HIGH); - pm_runtime_get_sync(mdwc->dev); dbg_event(0xFF, "StrtHost gync", atomic_read(&mdwc->dev->power.usage_count)); if (!IS_ERR(mdwc->vbus_reg)) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 1ffde9c5408c..9edc01692142 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -68,18 +68,27 @@ __ffs_data_got_descs(struct ffs_data *ffs, char *data, size_t len); static int __must_check __ffs_data_got_strings(struct ffs_data *ffs, char *data, size_t len); +static LIST_HEAD(inst_list); + /* ffs instance status */ -static DEFINE_MUTEX(ffs_ep_lock); -static bool ffs_inst_exist; -static struct f_fs_opts *g_opts; +#define INST_NAME_SIZE 16 -/* Free instance structures */ -static void ffs_inst_clean(struct f_fs_opts *opts); -static void ffs_inst_clean_delay(void); -static int ffs_inst_exist_check(void); +struct ffs_inst_status { + char inst_name[INST_NAME_SIZE]; + struct list_head list; + struct mutex ffs_lock; + bool inst_exist; + struct f_fs_opts *opts; + struct ffs_data *ffs_data; +}; -/* Global ffs_data pointer */ -static struct ffs_data *g_ffs_data; +/* Free instance structures */ +static void ffs_inst_clean(struct f_fs_opts *opts, + const char *inst_name); +static void ffs_inst_clean_delay(const char *inst_name); +static int ffs_inst_exist_check(const char *inst_name); +static struct ffs_inst_status *name_to_inst_status( + const char *inst_name, bool create_inst); /* The function structure ***************************************************/ @@ -300,7 +309,7 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf, ffs_log("enter:len %zu state %d setup_state %d flags %lu", len, ffs->state, ffs->setup_state, ffs->flags); - ret = ffs_inst_exist_check(); + ret = ffs_inst_exist_check(ffs->dev_name); if (ret < 0) return ret; @@ -490,7 +499,7 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf, ffs_log("enter:len %zu state %d setup_state %d flags %lu", len, ffs->state, ffs->setup_state, ffs->flags); - ret = ffs_inst_exist_check(); + ret = ffs_inst_exist_check(ffs->dev_name); if (ret < 0) return ret; @@ -601,7 +610,7 @@ static int ffs_ep0_open(struct inode *inode, struct file *file) ffs_log("state %d setup_state %d flags %lu opened %d", ffs->state, ffs->setup_state, ffs->flags, atomic_read(&ffs->opened)); - ret = ffs_inst_exist_check(); + ret = ffs_inst_exist_check(ffs->dev_name); if (ret < 0) return ret; @@ -643,7 +652,7 @@ static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value) ffs_log("state %d setup_state %d flags %lu opened %d", ffs->state, ffs->setup_state, ffs->flags, atomic_read(&ffs->opened)); - ret = ffs_inst_exist_check(); + ret = ffs_inst_exist_check(ffs->dev_name); if (ret < 0) return ret; @@ -668,7 +677,7 @@ static unsigned int ffs_ep0_poll(struct file *file, poll_table *wait) ffs_log("enter:state %d setup_state %d flags %lu opened %d", ffs->state, ffs->setup_state, ffs->flags, atomic_read(&ffs->opened)); - ret = ffs_inst_exist_check(); + ret = ffs_inst_exist_check(ffs->dev_name); if (ret < 0) return ret; @@ -799,6 +808,10 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) ffs_log("enter: epfile name %s epfile err %d (%s)", epfile->name, atomic_read(&epfile->error), io_data->read ? "READ" : "WRITE"); + ret = ffs_inst_exist_check(epfile->ffs->dev_name); + if (ret < 0) + return ret; + smp_mb__before_atomic(); retry: if (atomic_read(&epfile->error)) @@ -1085,7 +1098,7 @@ ffs_epfile_open(struct inode *inode, struct file *file) ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state, epfile->ffs->setup_state, epfile->ffs->flags); - ret = ffs_inst_exist_check(); + ret = ffs_inst_exist_check(epfile->ffs->dev_name); if (ret < 0) return ret; @@ -1143,16 +1156,11 @@ static ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from) { struct ffs_io_data io_data, *p = &io_data; ssize_t res; - int ret; ENTER(); ffs_log("enter"); - ret = ffs_inst_exist_check(); - if (ret < 0) - return ret; - if (!is_sync_kiocb(kiocb)) { p = kmalloc(sizeof(io_data), GFP_KERNEL); if (unlikely(!p)) @@ -1189,16 +1197,11 @@ static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to) { struct ffs_io_data io_data, *p = &io_data; ssize_t res; - int ret; ENTER(); ffs_log("enter"); - ret = ffs_inst_exist_check(); - if (ret < 0) - return ret; - if (!is_sync_kiocb(kiocb)) { p = kmalloc(sizeof(io_data), GFP_KERNEL); if (unlikely(!p)) @@ -1275,7 +1278,7 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code, ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state, epfile->ffs->setup_state, epfile->ffs->flags); - ret = ffs_inst_exist_check(); + ret = ffs_inst_exist_check(epfile->ffs->dev_name); if (ret < 0) return ret; @@ -1583,6 +1586,7 @@ ffs_fs_mount(struct file_system_type *t, int flags, int ret; void *ffs_dev; struct ffs_data *ffs; + struct ffs_inst_status *inst_status; ENTER(); @@ -1612,6 +1616,18 @@ ffs_fs_mount(struct file_system_type *t, int flags, ffs->private_data = ffs_dev; data.ffs_data = ffs; + inst_status = name_to_inst_status(ffs->dev_name, false); + if (IS_ERR(inst_status)) { + ffs_log("failed to find instance (%s)\n", + ffs->dev_name); + return ERR_PTR(-EINVAL); + } + + /* Store ffs to global status structure */ + ffs_dev_lock(); + inst_status->ffs_data = ffs; + ffs_dev_unlock(); + rv = mount_nodev(t, flags, &data, ffs_sb_fill); if (IS_ERR(rv) && data.ffs_data) { ffs_release_dev(data.ffs_data); @@ -1711,6 +1727,9 @@ static void ffs_data_opened(struct ffs_data *ffs) static void ffs_data_put(struct ffs_data *ffs) { + struct ffs_inst_status *inst_status; + const char *dev_name; + ENTER(); ffs_log("enter"); @@ -1718,16 +1737,20 @@ static void ffs_data_put(struct ffs_data *ffs) smp_mb__before_atomic(); if (unlikely(atomic_dec_and_test(&ffs->ref))) { pr_info("%s(): freeing\n", __func__); - /* Clear g_ffs_data */ - ffs_dev_lock(); - g_ffs_data = NULL; - ffs_dev_unlock(); + /* Clear ffs from global structure */ + inst_status = name_to_inst_status(ffs->dev_name, false); + if (!IS_ERR(inst_status)) { + ffs_dev_lock(); + inst_status->ffs_data = NULL; + ffs_dev_unlock(); + } ffs_data_clear(ffs); BUG_ON(waitqueue_active(&ffs->ev.waitq) || waitqueue_active(&ffs->ep0req_completion.wait)); - kfree(ffs->dev_name); + dev_name = ffs->dev_name; kfree(ffs); - ffs_inst_clean_delay(); + ffs_inst_clean_delay(dev_name); + kfree(dev_name); } ffs_log("exit"); @@ -1792,11 +1815,6 @@ static struct ffs_data *ffs_data_new(void) /* XXX REVISIT need to update it in some places, or do we? */ ffs->ev.can_stall = 1; - /* Store ffs to g_ffs_data */ - ffs_dev_lock(); - g_ffs_data = ffs; - ffs_dev_unlock(); - ffs_log("exit"); return ffs; @@ -3684,79 +3702,146 @@ static struct config_item_type ffs_func_type = { /* Function registration interface ******************************************/ -static int ffs_inst_exist_check(void) +static struct ffs_inst_status *name_to_inst_status( + const char *inst_name, bool create_inst) +{ + struct ffs_inst_status *inst_status; + + list_for_each_entry(inst_status, &inst_list, list) { + if (!strncasecmp(inst_status->inst_name, + inst_name, strlen(inst_name))) + return inst_status; + } + + if (!create_inst) + return ERR_PTR(-ENODEV); + + inst_status = kzalloc(sizeof(struct ffs_inst_status), + GFP_KERNEL); + if (!inst_status) + return ERR_PTR(-ENOMEM); + + mutex_init(&inst_status->ffs_lock); + snprintf(inst_status->inst_name, INST_NAME_SIZE, inst_name); + list_add_tail(&inst_status->list, &inst_list); + + return inst_status; +} + +static int ffs_inst_exist_check(const char *inst_name) { - mutex_lock(&ffs_ep_lock); + struct ffs_inst_status *inst_status; - if (unlikely(ffs_inst_exist == false)) { - mutex_unlock(&ffs_ep_lock); + inst_status = name_to_inst_status(inst_name, false); + if (IS_ERR(inst_status)) { pr_err_ratelimited( - "%s: f_fs instance freed already.\n", - __func__); + "%s: failed to find instance (%s)\n", + __func__, inst_name); + return -ENODEV; + } + + mutex_lock(&inst_status->ffs_lock); + + if (unlikely(inst_status->inst_exist == false)) { + mutex_unlock(&inst_status->ffs_lock); + pr_err_ratelimited( + "%s: f_fs instance (%s) has been freed already.\n", + __func__, inst_name); return -ENODEV; } - mutex_unlock(&ffs_ep_lock); + mutex_unlock(&inst_status->ffs_lock); return 0; } -static void ffs_inst_clean(struct f_fs_opts *opts) +static void ffs_inst_clean(struct f_fs_opts *opts, + const char *inst_name) { - g_opts = NULL; + struct ffs_inst_status *inst_status; + + inst_status = name_to_inst_status(inst_name, false); + if (IS_ERR(inst_status)) { + pr_err_ratelimited( + "%s: failed to find instance (%s)\n", + __func__, inst_name); + return; + } + + inst_status->opts = NULL; + ffs_dev_lock(); _ffs_free_dev(opts->dev); ffs_dev_unlock(); kfree(opts); } -static void ffs_inst_clean_delay(void) +static void ffs_inst_clean_delay(const char *inst_name) { - mutex_lock(&ffs_ep_lock); + struct ffs_inst_status *inst_status; - if (unlikely(ffs_inst_exist == false)) { - if (g_opts) { - ffs_inst_clean(g_opts); + inst_status = name_to_inst_status(inst_name, false); + if (IS_ERR(inst_status)) { + pr_err_ratelimited( + "%s: failed to find (%s) instance\n", + __func__, inst_name); + return; + } + + mutex_lock(&inst_status->ffs_lock); + + if (unlikely(inst_status->inst_exist == false)) { + if (inst_status->opts) { + ffs_inst_clean(inst_status->opts, inst_name); pr_err_ratelimited("%s: Delayed free memory\n", __func__); } - mutex_unlock(&ffs_ep_lock); + mutex_unlock(&inst_status->ffs_lock); return; } - mutex_unlock(&ffs_ep_lock); + mutex_unlock(&inst_status->ffs_lock); } static void ffs_free_inst(struct usb_function_instance *f) { struct f_fs_opts *opts; + struct ffs_inst_status *inst_status; opts = to_f_fs_opts(f); - mutex_lock(&ffs_ep_lock); + inst_status = name_to_inst_status(opts->dev->name, false); + if (IS_ERR(inst_status)) { + ffs_log("failed to find (%s) instance\n", + opts->dev->name); + return; + } + + mutex_lock(&inst_status->ffs_lock); if (opts->dev->ffs_data && atomic_read(&opts->dev->ffs_data->opened)) { - ffs_inst_exist = false; - mutex_unlock(&ffs_ep_lock); - ffs_log("%s: Dev is open, free mem when dev close\n", - __func__); + inst_status->inst_exist = false; + mutex_unlock(&inst_status->ffs_lock); + ffs_log("Dev is open, free mem when dev (%s) close\n", + opts->dev->name); return; } - ffs_inst_clean(opts); - ffs_inst_exist = false; - g_opts = NULL; - mutex_unlock(&ffs_ep_lock); + ffs_inst_clean(opts, opts->dev->name); + inst_status->inst_exist = false; + mutex_unlock(&inst_status->ffs_lock); } #define MAX_INST_NAME_LEN 40 static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name) { - struct f_fs_opts *opts; + struct f_fs_opts *opts, *opts_prev; + struct ffs_data *ffs_data_tmp; char *ptr; const char *tmp; int name_len, ret; + struct ffs_inst_status *inst_status; name_len = strlen(name) + 1; if (name_len > MAX_INST_NAME_LEN) @@ -3766,13 +3851,22 @@ static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name) if (!ptr) return -ENOMEM; - mutex_lock(&ffs_ep_lock); - if (g_opts) { - mutex_unlock(&ffs_ep_lock); - ffs_log("%s: prev inst do not freed yet\n", __func__); + inst_status = name_to_inst_status(ptr, true); + if (IS_ERR(inst_status)) { + ffs_log("failed to create status struct for (%s) instance\n", + ptr); + return -EINVAL; + } + + mutex_lock(&inst_status->ffs_lock); + opts_prev = inst_status->opts; + if (opts_prev) { + mutex_unlock(&inst_status->ffs_lock); + ffs_log("instance (%s): prev inst do not freed yet\n", + inst_status->inst_name); return -EBUSY; } - mutex_unlock(&ffs_ep_lock); + mutex_unlock(&inst_status->ffs_lock); opts = to_f_fs_opts(fi); tmp = NULL; @@ -3794,8 +3888,9 @@ static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name) * ffs_private_data also need to update new allocated opts->dev * address. */ - if (g_ffs_data) - opts->dev->ffs_data = g_ffs_data; + ffs_data_tmp = inst_status->ffs_data; + if (ffs_data_tmp) + opts->dev->ffs_data = ffs_data_tmp; if (opts->dev->ffs_data) opts->dev->ffs_data->private_data = opts->dev; @@ -3804,10 +3899,10 @@ static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name) kfree(tmp); - mutex_lock(&ffs_ep_lock); - ffs_inst_exist = true; - g_opts = opts; - mutex_unlock(&ffs_ep_lock); + mutex_lock(&inst_status->ffs_lock); + inst_status->inst_exist = true; + inst_status->opts = opts; + mutex_unlock(&inst_status->ffs_lock); return 0; } @@ -4212,6 +4307,20 @@ module_init(ffs_init); static void __exit ffs_exit(void) { + struct ffs_inst_status *inst_status, *inst_status_tmp = NULL; + + list_for_each_entry(inst_status, &inst_list, list) { + if (inst_status_tmp) { + list_del(&inst_status_tmp->list); + kfree(inst_status_tmp); + } + inst_status_tmp = inst_status; + } + if (inst_status_tmp) { + list_del(&inst_status_tmp->list); + kfree(inst_status_tmp); + } + if (ffs_ipc_log) { ipc_log_context_destroy(ffs_ipc_log); ffs_ipc_log = NULL; diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.c b/drivers/video/fbdev/msm/mdp3_ctrl.c index d357a616b05e..dff8b63eea64 100644 --- a/drivers/video/fbdev/msm/mdp3_ctrl.c +++ b/drivers/video/fbdev/msm/mdp3_ctrl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, 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 @@ -1563,9 +1563,10 @@ static int mdp3_get_metadata(struct msm_fb_data_type *mfd, } break; case metadata_op_get_ion_fd: - if (mfd->fb_ion_handle) { + if (mfd->fb_ion_handle && mfd->fb_ion_client) { metadata->data.fbmem_ionfd = - dma_buf_fd(mfd->fbmem_buf, 0); + ion_share_dma_buf_fd(mfd->fb_ion_client, + mfd->fb_ion_handle); if (metadata->data.fbmem_ionfd < 0) pr_err("fd allocation failed. fd = %d\n", metadata->data.fbmem_ionfd); diff --git a/include/linux/habmm.h b/include/linux/habmm.h index 966c5ee91be4..842cd27fd372 100644 --- a/include/linux/habmm.h +++ b/include/linux/habmm.h @@ -214,6 +214,11 @@ int32_t habmm_socket_recvfrom(int32_t handle, void *dst_buff, */ #define HABMM_EXP_MEM_TYPE_DMA 0x00000001 +/* + * this flag is used for export from dma_buf fd or import to dma_buf fd + */ +#define HABMM_EXPIMP_FLAGS_FD 0x00010000 + #define HAB_MAX_EXPORT_SIZE 0x8000000 /* diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index c9e252bc4c2c..f564303a28f9 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -84,6 +84,8 @@ struct mmc_ios { #define MMC_SET_DRIVER_TYPE_A 1 #define MMC_SET_DRIVER_TYPE_C 2 #define MMC_SET_DRIVER_TYPE_D 3 + + bool enhanced_strobe; /* hs400es selection */ }; /* states to represent load on the host */ @@ -827,6 +829,11 @@ static inline bool mmc_card_hs400(struct mmc_card *card) return card->host->ios.timing == MMC_TIMING_MMC_HS400; } +static inline bool mmc_card_hs400es(struct mmc_card *card) +{ + return card->host->ios.enhanced_strobe; +} + void mmc_retune_enable(struct mmc_host *host); void mmc_retune_disable(struct mmc_host *host); void mmc_retune_timer_stop(struct mmc_host *host); diff --git a/include/linux/qdsp6v2/apr.h b/include/linux/qdsp6v2/apr.h index adcdbcbc5907..98432952f278 100644 --- a/include/linux/qdsp6v2/apr.h +++ b/include/linux/qdsp6v2/apr.h @@ -69,7 +69,9 @@ struct apr_hdr { #define APR_DOMAIN_MODEM 0x3 #define APR_DOMAIN_ADSP 0x4 #define APR_DOMAIN_APPS 0x5 -#define APR_DOMAIN_MAX 0x6 +#define APR_DOMAIN_SDSP 0x8 +#define APR_DOMAIN_MAX 0x9 + /* ADSP service IDs */ #define APR_SVC_TEST_CLIENT 0x2 @@ -94,6 +96,9 @@ struct apr_hdr { #define APR_SVC_CVP 0x6 #define APR_SVC_SRD 0x7 +/* Sensor DSP Micro Audio Service IDs */ +#define APR_SVC_MAS 0x3 + /* APR Port IDs */ #define APR_MAX_PORTS 0x80 diff --git a/include/linux/qdsp6v2/apr_tal.h b/include/linux/qdsp6v2/apr_tal.h index bf324064960b..9b35c9f9882d 100644 --- a/include/linux/qdsp6v2/apr_tal.h +++ b/include/linux/qdsp6v2/apr_tal.h @@ -27,7 +27,8 @@ #define APR_DEST_MODEM 0 #define APR_DEST_QDSP6 1 -#define APR_DEST_MAX 2 +#define APR_DEST_DSPS 3 +#define APR_DEST_MAX 4 #if defined(CONFIG_MSM_QDSP6_APRV2_GLINK) || \ defined(CONFIG_MSM_QDSP6_APRV3_GLINK) diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h index 5031e62beb17..922ebb69205d 100644 --- a/include/sound/q6afe-v2.h +++ b/include/sound/q6afe-v2.h @@ -208,6 +208,87 @@ enum { AFE_MAX_PORTS }; + +enum { + IDX_PRIMARY_TDM_RX_0, + IDX_PRIMARY_TDM_RX_1, + IDX_PRIMARY_TDM_RX_2, + IDX_PRIMARY_TDM_RX_3, + IDX_PRIMARY_TDM_RX_4, + IDX_PRIMARY_TDM_RX_5, + IDX_PRIMARY_TDM_RX_6, + IDX_PRIMARY_TDM_RX_7, + IDX_PRIMARY_TDM_TX_0, + IDX_PRIMARY_TDM_TX_1, + IDX_PRIMARY_TDM_TX_2, + IDX_PRIMARY_TDM_TX_3, + IDX_PRIMARY_TDM_TX_4, + IDX_PRIMARY_TDM_TX_5, + IDX_PRIMARY_TDM_TX_6, + IDX_PRIMARY_TDM_TX_7, + IDX_SECONDARY_TDM_RX_0, + IDX_SECONDARY_TDM_RX_1, + IDX_SECONDARY_TDM_RX_2, + IDX_SECONDARY_TDM_RX_3, + IDX_SECONDARY_TDM_RX_4, + IDX_SECONDARY_TDM_RX_5, + IDX_SECONDARY_TDM_RX_6, + IDX_SECONDARY_TDM_RX_7, + IDX_SECONDARY_TDM_TX_0, + IDX_SECONDARY_TDM_TX_1, + IDX_SECONDARY_TDM_TX_2, + IDX_SECONDARY_TDM_TX_3, + IDX_SECONDARY_TDM_TX_4, + IDX_SECONDARY_TDM_TX_5, + IDX_SECONDARY_TDM_TX_6, + IDX_SECONDARY_TDM_TX_7, + IDX_TERTIARY_TDM_RX_0, + IDX_TERTIARY_TDM_RX_1, + IDX_TERTIARY_TDM_RX_2, + IDX_TERTIARY_TDM_RX_3, + IDX_TERTIARY_TDM_RX_4, + IDX_TERTIARY_TDM_RX_5, + IDX_TERTIARY_TDM_RX_6, + IDX_TERTIARY_TDM_RX_7, + IDX_TERTIARY_TDM_TX_0, + IDX_TERTIARY_TDM_TX_1, + IDX_TERTIARY_TDM_TX_2, + IDX_TERTIARY_TDM_TX_3, + IDX_TERTIARY_TDM_TX_4, + IDX_TERTIARY_TDM_TX_5, + IDX_TERTIARY_TDM_TX_6, + IDX_TERTIARY_TDM_TX_7, + IDX_QUATERNARY_TDM_RX_0, + IDX_QUATERNARY_TDM_RX_1, + IDX_QUATERNARY_TDM_RX_2, + IDX_QUATERNARY_TDM_RX_3, + IDX_QUATERNARY_TDM_RX_4, + IDX_QUATERNARY_TDM_RX_5, + IDX_QUATERNARY_TDM_RX_6, + IDX_QUATERNARY_TDM_RX_7, + IDX_QUATERNARY_TDM_TX_0, + IDX_QUATERNARY_TDM_TX_1, + IDX_QUATERNARY_TDM_TX_2, + IDX_QUATERNARY_TDM_TX_3, + IDX_QUATERNARY_TDM_TX_4, + IDX_QUATERNARY_TDM_TX_5, + IDX_QUATERNARY_TDM_TX_6, + IDX_QUATERNARY_TDM_TX_7, + IDX_TDM_MAX, +}; + +enum { + IDX_GROUP_PRIMARY_TDM_RX, + IDX_GROUP_PRIMARY_TDM_TX, + IDX_GROUP_SECONDARY_TDM_RX, + IDX_GROUP_SECONDARY_TDM_TX, + IDX_GROUP_TERTIARY_TDM_RX, + IDX_GROUP_TERTIARY_TDM_TX, + IDX_GROUP_QUATERNARY_TDM_RX, + IDX_GROUP_QUATERNARY_TDM_TX, + IDX_GROUP_TDM_MAX, +}; + enum afe_mad_type { MAD_HW_NONE = 0x00, MAD_HW_AUDIO = 0x01, diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h index 3b91ad5d5115..2dd096eea935 100644 --- a/include/sound/rawmidi.h +++ b/include/sound/rawmidi.h @@ -78,6 +78,7 @@ struct snd_rawmidi_runtime { size_t xruns; /* over/underruns counter */ /* misc */ spinlock_t lock; + struct mutex realloc_mutex; wait_queue_head_t sleep; /* event handler (new bytes, input only) */ void (*event)(struct snd_rawmidi_substream *substream); diff --git a/include/trace/events/preemptirq.h b/include/trace/events/preemptirq.h index f5024c560d8f..9c4eb33c5a1d 100644 --- a/include/trace/events/preemptirq.h +++ b/include/trace/events/preemptirq.h @@ -56,15 +56,18 @@ DEFINE_EVENT(preemptirq_template, preempt_enable, #include <trace/define_trace.h> -#else /* !CONFIG_PREEMPTIRQ_EVENTS */ +#endif /* !CONFIG_PREEMPTIRQ_EVENTS */ +#if !defined(CONFIG_PREEMPTIRQ_EVENTS) || defined(CONFIG_PROVE_LOCKING) #define trace_irq_enable(...) #define trace_irq_disable(...) -#define trace_preempt_enable(...) -#define trace_preempt_disable(...) #define trace_irq_enable_rcuidle(...) #define trace_irq_disable_rcuidle(...) +#endif + +#if !defined(CONFIG_PREEMPTIRQ_EVENTS) || !defined(CONFIG_DEBUG_PREEMPT) +#define trace_preempt_enable(...) +#define trace_preempt_disable(...) #define trace_preempt_enable_rcuidle(...) #define trace_preempt_disable_rcuidle(...) - #endif diff --git a/include/uapi/media/msm_camera.h b/include/uapi/media/msm_camera.h index 39e6927d9b7e..fd0937ffb1e5 100644 --- a/include/uapi/media/msm_camera.h +++ b/include/uapi/media/msm_camera.h @@ -1,4 +1,5 @@ -/* Copyright (c) 2009-2012, 2014-2016 The Linux Foundation. All rights reserved. +/* Copyright (c) 2009-2012, 2014-2016, 2018 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 @@ -1386,6 +1387,7 @@ struct msm_camera_csiphy_params { uint16_t lane_mask; uint8_t combo_mode; uint8_t csid_core; + uint64_t data_rate; }; struct msm_camera_csi2_params { diff --git a/include/uapi/media/msm_camsensor_sdk.h b/include/uapi/media/msm_camsensor_sdk.h index 08605aca474d..ac454ca9a7fc 100644 --- a/include/uapi/media/msm_camsensor_sdk.h +++ b/include/uapi/media/msm_camsensor_sdk.h @@ -367,6 +367,7 @@ struct msm_camera_csiphy_params { unsigned char csid_core; unsigned int csiphy_clk; unsigned char csi_3phase; + uint64_t data_rate; }; struct msm_camera_i2c_seq_reg_array { diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c index 5f60666d4c79..bfb76a84be73 100644 --- a/net/ipc_router/ipc_router_core.c +++ b/net/ipc_router/ipc_router_core.c @@ -224,6 +224,25 @@ void msm_ipc_router_set_ws_allowed(bool flag) is_wakeup_source_allowed = flag; } +/** + * is_sensor_port() - Check if the remote port is sensor service or not + * @rport: Pointer to the remote port. + * + * Return: true if the remote port is sensor service else false. + */ +static int is_sensor_port(struct msm_ipc_router_remote_port *rport) +{ + u32 svcid = 0; + + if (rport && rport->server) { + svcid = rport->server->name.service; + if (svcid == 400 || (svcid >= 256 && svcid <= 320)) + return true; + } + + return false; +} + static void init_routing_table(void) { int i; @@ -2731,7 +2750,6 @@ static void do_read_data(struct work_struct *work) struct rr_packet *pkt = NULL; struct msm_ipc_port *port_ptr; struct msm_ipc_router_remote_port *rport_ptr; - int ret; struct msm_ipc_router_xprt_info *xprt_info = container_of(work, @@ -2739,16 +2757,7 @@ static void do_read_data(struct work_struct *work) read_data); while ((pkt = rr_read(xprt_info)) != NULL) { - if (pkt->length < calc_rx_header_size(xprt_info) || - pkt->length > MAX_IPC_PKT_SIZE) { - IPC_RTR_ERR("%s: Invalid pkt length %d\n", - __func__, pkt->length); - goto read_next_pkt1; - } - ret = extract_header(pkt); - if (ret < 0) - goto read_next_pkt1; hdr = &(pkt->hdr); if ((hdr->dst_node_id != IPC_ROUTER_NID_LOCAL) && @@ -4195,6 +4204,7 @@ void msm_ipc_router_xprt_notify(struct msm_ipc_router_xprt *xprt, { struct msm_ipc_router_xprt_info *xprt_info = xprt->priv; struct msm_ipc_router_xprt_work *xprt_work; + struct msm_ipc_router_remote_port *rport_ptr = NULL; struct rr_packet *pkt; int ret; @@ -4247,16 +4257,40 @@ void msm_ipc_router_xprt_notify(struct msm_ipc_router_xprt *xprt, if (!pkt) return; + if (pkt->length < calc_rx_header_size(xprt_info) || + pkt->length > MAX_IPC_PKT_SIZE) { + IPC_RTR_ERR("%s: Invalid pkt length %d\n", + __func__, pkt->length); + release_pkt(pkt); + return; + } + + ret = extract_header(pkt); + if (ret < 0) { + release_pkt(pkt); + return; + } + pkt->ws_need = false; + + if (pkt->hdr.type == IPC_ROUTER_CTRL_CMD_DATA) + rport_ptr = ipc_router_get_rport_ref(pkt->hdr.src_node_id, + pkt->hdr.src_port_id); + mutex_lock(&xprt_info->rx_lock_lhb2); list_add_tail(&pkt->list, &xprt_info->pkt_list); - if (!xprt_info->dynamic_ws) { - __pm_stay_awake(&xprt_info->ws); - pkt->ws_need = true; - } else { - if (is_wakeup_source_allowed) { + /* check every pkt is from SENSOR services or not and + * avoid holding both edge and port specific wake-up sources + */ + if (!is_sensor_port(rport_ptr)) { + if (!xprt_info->dynamic_ws) { __pm_stay_awake(&xprt_info->ws); pkt->ws_need = true; + } else { + if (is_wakeup_source_allowed) { + __pm_stay_awake(&xprt_info->ws); + pkt->ws_need = true; + } } } mutex_unlock(&xprt_info->rx_lock_lhb2); diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 16f8124b1150..514380104944 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -115,6 +115,7 @@ static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream) return -ENOMEM; runtime->substream = substream; spin_lock_init(&runtime->lock); + mutex_init(&runtime->realloc_mutex); init_waitqueue_head(&runtime->sleep); INIT_WORK(&runtime->event_work, snd_rawmidi_input_event_work); runtime->event = NULL; @@ -636,8 +637,10 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, struct snd_rawmidi_params * params) { char *newbuf; + char *oldbuf; struct snd_rawmidi_runtime *runtime = substream->runtime; - + unsigned long flags; + if (substream->append && substream->use_count > 1) return -EBUSY; snd_rawmidi_drain_output(substream); @@ -648,13 +651,22 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, return -EINVAL; } if (params->buffer_size != runtime->buffer_size) { - newbuf = krealloc(runtime->buffer, params->buffer_size, + mutex_lock(&runtime->realloc_mutex); + newbuf = __krealloc(runtime->buffer, params->buffer_size, GFP_KERNEL); - if (!newbuf) + if (!newbuf) { + mutex_unlock(&runtime->realloc_mutex); return -ENOMEM; + } + spin_lock_irqsave(&runtime->lock, flags); + oldbuf = runtime->buffer; runtime->buffer = newbuf; runtime->buffer_size = params->buffer_size; runtime->avail = runtime->buffer_size; + spin_unlock_irqrestore(&runtime->lock, flags); + if (oldbuf != newbuf) + kfree(oldbuf); + mutex_unlock(&runtime->realloc_mutex); } runtime->avail_min = params->avail_min; substream->active_sensing = !params->no_active_sensing; @@ -666,7 +678,9 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, struct snd_rawmidi_params * params) { char *newbuf; + char *oldbuf; struct snd_rawmidi_runtime *runtime = substream->runtime; + unsigned long flags; snd_rawmidi_drain_input(substream); if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) { @@ -676,12 +690,21 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, return -EINVAL; } if (params->buffer_size != runtime->buffer_size) { - newbuf = krealloc(runtime->buffer, params->buffer_size, + mutex_lock(&runtime->realloc_mutex); + newbuf = __krealloc(runtime->buffer, params->buffer_size, GFP_KERNEL); - if (!newbuf) + if (!newbuf) { + mutex_unlock(&runtime->realloc_mutex); return -ENOMEM; + } + spin_lock_irqsave(&runtime->lock, flags); + oldbuf = runtime->buffer; runtime->buffer = newbuf; runtime->buffer_size = params->buffer_size; + spin_unlock_irqrestore(&runtime->lock, flags); + if (oldbuf != newbuf) + kfree(oldbuf); + mutex_unlock(&runtime->realloc_mutex); } runtime->avail_min = params->avail_min; return 0; @@ -954,6 +977,8 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream, unsigned long appl_ptr; spin_lock_irqsave(&runtime->lock, flags); + if (userbuf) + mutex_lock(&runtime->realloc_mutex); while (count > 0 && runtime->avail) { count1 = runtime->buffer_size - runtime->appl_ptr; if (count1 > count) @@ -973,6 +998,7 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream, spin_unlock_irqrestore(&runtime->lock, flags); if (copy_to_user(userbuf + result, runtime->buffer + appl_ptr, count1)) { + mutex_unlock(&runtime->realloc_mutex); return result > 0 ? result : -EFAULT; } spin_lock_irqsave(&runtime->lock, flags); @@ -981,6 +1007,8 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream, count -= count1; } spin_unlock_irqrestore(&runtime->lock, flags); + if (userbuf) + mutex_unlock(&runtime->realloc_mutex); return result; } @@ -1245,10 +1273,14 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream, return -EINVAL; result = 0; + if (userbuf) + mutex_lock(&runtime->realloc_mutex); spin_lock_irqsave(&runtime->lock, flags); if (substream->append) { if ((long)runtime->avail < count) { spin_unlock_irqrestore(&runtime->lock, flags); + if (userbuf) + mutex_unlock(&runtime->realloc_mutex); return -EAGAIN; } } @@ -1284,6 +1316,8 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream, __end: count1 = runtime->avail < runtime->buffer_size; spin_unlock_irqrestore(&runtime->lock, flags); + if (userbuf) + mutex_unlock(&runtime->realloc_mutex); if (count1) snd_rawmidi_output_trigger(substream, 1); return result; diff --git a/sound/soc/msm/apq8096-auto.c b/sound/soc/msm/apq8096-auto.c index d6473cccf496..0de8b0237aae 100644 --- a/sound/soc/msm/apq8096-auto.c +++ b/sound/soc/msm/apq8096-auto.c @@ -5122,20 +5122,22 @@ static struct snd_soc_dai_link apq8096_common_dai_links[] = { .be_id = MSM_FRONTEND_DAI_LSM7, }, { - .name = "Listen 8 Audio Service", - .stream_name = "Listen 8 Audio Service", - .cpu_dai_name = "LSM8", - .platform_name = "msm-lsm-client", + .name = "MSM8996 LowLatency2", + .stream_name = "MultiMedia22", + .cpu_dai_name = "MultiMedia22", + .platform_name = "msm-pcm-dsp.1", .dynamic = 1, - .dpcm_capture = 1, - .trigger = { SND_SOC_DPCM_TRIGGER_POST, - SND_SOC_DPCM_TRIGGER_POST }, - .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, - .ignore_suspend = 1, - .ignore_pmdown_time = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE, + .dpcm_playback = 1, .codec_dai_name = "snd-soc-dummy-dai", .codec_name = "snd-soc-dummy", - .be_id = MSM_FRONTEND_DAI_LSM8, + .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, + .ops = &apq8096_ll_ops, }, { .name = "MSM8996 LowLatency Loopback", diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c index 26b40d2081f0..8098db80194d 100644 --- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c @@ -91,86 +91,6 @@ enum { RATE_MAX_NUM_OF_AUX_PCM_RATES, }; -enum { - IDX_PRIMARY_TDM_RX_0, - IDX_PRIMARY_TDM_RX_1, - IDX_PRIMARY_TDM_RX_2, - IDX_PRIMARY_TDM_RX_3, - IDX_PRIMARY_TDM_RX_4, - IDX_PRIMARY_TDM_RX_5, - IDX_PRIMARY_TDM_RX_6, - IDX_PRIMARY_TDM_RX_7, - IDX_PRIMARY_TDM_TX_0, - IDX_PRIMARY_TDM_TX_1, - IDX_PRIMARY_TDM_TX_2, - IDX_PRIMARY_TDM_TX_3, - IDX_PRIMARY_TDM_TX_4, - IDX_PRIMARY_TDM_TX_5, - IDX_PRIMARY_TDM_TX_6, - IDX_PRIMARY_TDM_TX_7, - IDX_SECONDARY_TDM_RX_0, - IDX_SECONDARY_TDM_RX_1, - IDX_SECONDARY_TDM_RX_2, - IDX_SECONDARY_TDM_RX_3, - IDX_SECONDARY_TDM_RX_4, - IDX_SECONDARY_TDM_RX_5, - IDX_SECONDARY_TDM_RX_6, - IDX_SECONDARY_TDM_RX_7, - IDX_SECONDARY_TDM_TX_0, - IDX_SECONDARY_TDM_TX_1, - IDX_SECONDARY_TDM_TX_2, - IDX_SECONDARY_TDM_TX_3, - IDX_SECONDARY_TDM_TX_4, - IDX_SECONDARY_TDM_TX_5, - IDX_SECONDARY_TDM_TX_6, - IDX_SECONDARY_TDM_TX_7, - IDX_TERTIARY_TDM_RX_0, - IDX_TERTIARY_TDM_RX_1, - IDX_TERTIARY_TDM_RX_2, - IDX_TERTIARY_TDM_RX_3, - IDX_TERTIARY_TDM_RX_4, - IDX_TERTIARY_TDM_RX_5, - IDX_TERTIARY_TDM_RX_6, - IDX_TERTIARY_TDM_RX_7, - IDX_TERTIARY_TDM_TX_0, - IDX_TERTIARY_TDM_TX_1, - IDX_TERTIARY_TDM_TX_2, - IDX_TERTIARY_TDM_TX_3, - IDX_TERTIARY_TDM_TX_4, - IDX_TERTIARY_TDM_TX_5, - IDX_TERTIARY_TDM_TX_6, - IDX_TERTIARY_TDM_TX_7, - IDX_QUATERNARY_TDM_RX_0, - IDX_QUATERNARY_TDM_RX_1, - IDX_QUATERNARY_TDM_RX_2, - IDX_QUATERNARY_TDM_RX_3, - IDX_QUATERNARY_TDM_RX_4, - IDX_QUATERNARY_TDM_RX_5, - IDX_QUATERNARY_TDM_RX_6, - IDX_QUATERNARY_TDM_RX_7, - IDX_QUATERNARY_TDM_TX_0, - IDX_QUATERNARY_TDM_TX_1, - IDX_QUATERNARY_TDM_TX_2, - IDX_QUATERNARY_TDM_TX_3, - IDX_QUATERNARY_TDM_TX_4, - IDX_QUATERNARY_TDM_TX_5, - IDX_QUATERNARY_TDM_TX_6, - IDX_QUATERNARY_TDM_TX_7, - IDX_TDM_MAX, -}; - -enum { - IDX_GROUP_PRIMARY_TDM_RX, - IDX_GROUP_PRIMARY_TDM_TX, - IDX_GROUP_SECONDARY_TDM_RX, - IDX_GROUP_SECONDARY_TDM_TX, - IDX_GROUP_TERTIARY_TDM_RX, - IDX_GROUP_TERTIARY_TDM_TX, - IDX_GROUP_QUATERNARY_TDM_RX, - IDX_GROUP_QUATERNARY_TDM_TX, - IDX_GROUP_TDM_MAX, -}; - struct msm_dai_q6_dai_data { DECLARE_BITMAP(status_mask, STATUS_MAX); DECLARE_BITMAP(hwfree_status, STATUS_MAX); diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c index 5d3d24b058d3..9af5de2952d4 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c @@ -847,7 +847,7 @@ static int msm_pcm_channel_mixer_output_map_ctl_put( } chmixer_pspd = &(pdata->chmixer_pspd[fe_id][session_type]); - for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++) + for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V2; i++) chmixer_pspd->out_ch_map[i] = ucontrol->value.integer.value[i]; @@ -878,7 +878,7 @@ static int msm_pcm_channel_mixer_output_map_ctl_get( } chmixer_pspd = &(pdata->chmixer_pspd[fe_id][session_type]); - for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++) + for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V2; i++) ucontrol->value.integer.value[i] = chmixer_pspd->out_ch_map[i]; return 0; @@ -908,7 +908,7 @@ static int msm_pcm_channel_mixer_input_map_ctl_put( } chmixer_pspd = &(pdata->chmixer_pspd[fe_id][session_type]); - for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++) + for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V2; i++) chmixer_pspd->in_ch_map[i] = ucontrol->value.integer.value[i]; return 0; @@ -938,7 +938,7 @@ static int msm_pcm_channel_mixer_input_map_ctl_get( } chmixer_pspd = &(pdata->chmixer_pspd[fe_id][session_type]); - for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++) + for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V2; i++) ucontrol->value.integer.value[i] = chmixer_pspd->in_ch_map[i]; return 0; @@ -969,13 +969,13 @@ static int msm_pcm_channel_mixer_weight_ctl_put( } chmixer_pspd = &(pdata->chmixer_pspd[fe_id][session_type]); - if (channel <= 0 || channel > PCM_FORMAT_MAX_NUM_CHANNEL) { + if (channel <= 0 || channel > PCM_FORMAT_MAX_NUM_CHANNEL_V2) { pr_err("%s: invalid channel number %d\n", __func__, channel); return -EINVAL; } channel--; - for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++) + for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V2; i++) chmixer_pspd->channel_weight[channel][i] = ucontrol->value.integer.value[i]; return 0; @@ -1005,14 +1005,14 @@ static int msm_pcm_channel_mixer_weight_ctl_get( return -EINVAL; } - if (channel <= 0 || channel > PCM_FORMAT_MAX_NUM_CHANNEL) { + if (channel <= 0 || channel > PCM_FORMAT_MAX_NUM_CHANNEL_V2) { pr_err("%s: invalid channel number %d\n", __func__, channel); return -EINVAL; } channel--; chmixer_pspd = &(pdata->chmixer_pspd[fe_id][session_type]); - for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++) + for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V2; i++) ucontrol->value.integer.value[i] = chmixer_pspd->channel_weight[channel][i]; return 0; @@ -1462,7 +1462,7 @@ static int msm_pcm_add_channel_mixer_controls(struct snd_soc_pcm_runtime *rtd) pr_err("%s: pcm add channel mixer output map controls failed:%d\n", __func__, ret); - for (i = 1; i <= PCM_FORMAT_MAX_NUM_CHANNEL; i++) + for (i = 1; i <= PCM_FORMAT_MAX_NUM_CHANNEL_V2; i++) ret |= msm_pcm_add_channel_mixer_weight_controls(rtd, i); if (ret) pr_err("%s: pcm add channel mixer weight controls failed:%d\n", diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c index a0364bbdfeb9..11b86cb5ff5c 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c @@ -2263,7 +2263,7 @@ static int msm_pcm_channel_mixer_output_map_ctl_put( } chmixer_pspd = &(pdata->chmixer_pspd[fe_id][session_type]); - for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++) + for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V2; i++) chmixer_pspd->out_ch_map[i] = ucontrol->value.integer.value[i]; @@ -2294,7 +2294,7 @@ static int msm_pcm_channel_mixer_output_map_ctl_get( } chmixer_pspd = &(pdata->chmixer_pspd[fe_id][session_type]); - for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++) + for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V2; i++) ucontrol->value.integer.value[i] = chmixer_pspd->out_ch_map[i]; return 0; @@ -2324,7 +2324,7 @@ static int msm_pcm_channel_mixer_input_map_ctl_put( } chmixer_pspd = &(pdata->chmixer_pspd[fe_id][session_type]); - for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++) + for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V2; i++) chmixer_pspd->in_ch_map[i] = ucontrol->value.integer.value[i]; return 0; @@ -2354,7 +2354,7 @@ static int msm_pcm_channel_mixer_input_map_ctl_get( } chmixer_pspd = &(pdata->chmixer_pspd[fe_id][session_type]); - for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++) + for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V2; i++) ucontrol->value.integer.value[i] = chmixer_pspd->in_ch_map[i]; return 0; @@ -2385,13 +2385,13 @@ static int msm_pcm_channel_mixer_weight_ctl_put( } chmixer_pspd = &(pdata->chmixer_pspd[fe_id][session_type]); - if (channel <= 0 || channel > PCM_FORMAT_MAX_NUM_CHANNEL) { + if (channel <= 0 || channel > PCM_FORMAT_MAX_NUM_CHANNEL_V2) { pr_err("%s: invalid channel number %d\n", __func__, channel); return -EINVAL; } channel--; - for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++) + for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V2; i++) chmixer_pspd->channel_weight[channel][i] = ucontrol->value.integer.value[i]; return 0; @@ -2421,14 +2421,14 @@ static int msm_pcm_channel_mixer_weight_ctl_get( return -EINVAL; } - if (channel <= 0 || channel > PCM_FORMAT_MAX_NUM_CHANNEL) { + if (channel <= 0 || channel > PCM_FORMAT_MAX_NUM_CHANNEL_V2) { pr_err("%s: invalid channel number %d\n", __func__, channel); return -EINVAL; } channel--; chmixer_pspd = &(pdata->chmixer_pspd[fe_id][session_type]); - for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++) + for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V2; i++) ucontrol->value.integer.value[i] = chmixer_pspd->channel_weight[channel][i]; return 0; @@ -2878,7 +2878,7 @@ static int msm_pcm_add_channel_mixer_controls(struct snd_soc_pcm_runtime *rtd) pr_err("%s: pcm add channel mixer output map controls failed:%d\n", __func__, ret); - for (i = 1; i <= PCM_FORMAT_MAX_NUM_CHANNEL; i++) + for (i = 1; i <= PCM_FORMAT_MAX_NUM_CHANNEL_V2; i++) ret |= msm_pcm_add_channel_mixer_weight_controls(rtd, i); if (ret) pr_err("%s: pcm add channel mixer weight controls failed:%d\n", diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index 2b712bee0bc1..8a28c4fa6746 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -5844,6 +5844,9 @@ static const struct snd_kcontrol_new pri_tdm_rx_0_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_PRI_TDM_RX_0, MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_PRI_TDM_RX_0, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_PRI_TDM_RX_0, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -5901,6 +5904,9 @@ static const struct snd_kcontrol_new pri_tdm_rx_1_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_PRI_TDM_RX_1, MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_PRI_TDM_RX_1, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -5958,6 +5964,9 @@ static const struct snd_kcontrol_new pri_tdm_rx_2_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_PRI_TDM_RX_2, MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_PRI_TDM_RX_2, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -6015,6 +6024,9 @@ static const struct snd_kcontrol_new pri_tdm_rx_3_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_PRI_TDM_RX_3, MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_PRI_TDM_RX_3, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -6123,6 +6135,9 @@ static const struct snd_kcontrol_new sec_tdm_rx_0_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_SEC_TDM_RX_0, MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_SEC_TDM_RX_0, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_SEC_TDM_RX_0, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -6180,6 +6195,9 @@ static const struct snd_kcontrol_new sec_tdm_rx_1_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_SEC_TDM_RX_1, MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_SEC_TDM_RX_1, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -6237,6 +6255,9 @@ static const struct snd_kcontrol_new sec_tdm_rx_2_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_SEC_TDM_RX_2, MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_SEC_TDM_RX_2, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -6294,6 +6315,9 @@ static const struct snd_kcontrol_new sec_tdm_rx_3_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_SEC_TDM_RX_3, MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_SEC_TDM_RX_3, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -6402,6 +6426,9 @@ static const struct snd_kcontrol_new tert_tdm_rx_0_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_TERT_TDM_RX_0, MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_TERT_TDM_RX_0, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_TERT_TDM_RX_0, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -6510,6 +6537,9 @@ static const struct snd_kcontrol_new tert_tdm_rx_1_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_TERT_TDM_RX_1, MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_TERT_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_TERT_TDM_RX_1, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -6567,6 +6597,9 @@ static const struct snd_kcontrol_new tert_tdm_rx_2_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_TERT_TDM_RX_2, MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_TERT_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_TERT_TDM_RX_2, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -6624,6 +6657,9 @@ static const struct snd_kcontrol_new tert_tdm_rx_3_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_TERT_TDM_RX_3, MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_TERT_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_TERT_TDM_RX_3, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -6681,6 +6717,9 @@ static const struct snd_kcontrol_new tert_tdm_rx_4_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_TERT_TDM_RX_4, MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_TERT_TDM_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_TERT_TDM_RX_4, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -6741,6 +6780,9 @@ static const struct snd_kcontrol_new quat_tdm_rx_0_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_QUAT_TDM_RX_0, MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_QUAT_TDM_RX_0, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_QUAT_TDM_RX_0, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -6852,6 +6894,9 @@ static const struct snd_kcontrol_new quat_tdm_rx_1_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_QUAT_TDM_RX_1, MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_QUAT_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_QUAT_TDM_RX_1, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -6912,6 +6957,9 @@ static const struct snd_kcontrol_new quat_tdm_rx_2_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_QUAT_TDM_RX_2, MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_QUAT_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_QUAT_TDM_RX_2, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -6972,6 +7020,9 @@ static const struct snd_kcontrol_new quat_tdm_rx_3_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_QUAT_TDM_RX_3, MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_QUAT_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_QUAT_TDM_RX_3, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -13780,6 +13831,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia15", "MM_DL15"}, {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia22", "MM_DL22"}, {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia26", "MM_DL26"}, {"PRI_TDM_RX_0", NULL, "PRI_TDM_RX_0 Audio Mixer"}, @@ -13800,6 +13852,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia15", "MM_DL15"}, {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia22", "MM_DL22"}, {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia26", "MM_DL26"}, {"PRI_TDM_RX_1", NULL, "PRI_TDM_RX_1 Audio Mixer"}, @@ -13820,6 +13873,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia15", "MM_DL15"}, {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia22", "MM_DL22"}, {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia26", "MM_DL26"}, {"PRI_TDM_RX_2", NULL, "PRI_TDM_RX_2 Audio Mixer"}, @@ -13840,6 +13894,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia15", "MM_DL15"}, {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia22", "MM_DL22"}, {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia26", "MM_DL26"}, {"PRI_TDM_RX_3", NULL, "PRI_TDM_RX_3 Audio Mixer"}, @@ -13878,6 +13933,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia15", "MM_DL15"}, {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia22", "MM_DL22"}, {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia26", "MM_DL26"}, {"SEC_TDM_RX_0", NULL, "SEC_TDM_RX_0 Audio Mixer"}, @@ -13898,6 +13954,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia15", "MM_DL15"}, {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia22", "MM_DL22"}, {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia26", "MM_DL26"}, {"SEC_TDM_RX_1", NULL, "SEC_TDM_RX_1 Audio Mixer"}, @@ -13918,6 +13975,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia15", "MM_DL15"}, {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia22", "MM_DL22"}, {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia26", "MM_DL26"}, {"SEC_TDM_RX_2", NULL, "SEC_TDM_RX_2 Audio Mixer"}, @@ -13938,6 +13996,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia15", "MM_DL15"}, {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia22", "MM_DL22"}, {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia26", "MM_DL26"}, {"SEC_TDM_RX_3", NULL, "SEC_TDM_RX_3 Audio Mixer"}, @@ -13976,6 +14035,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"TERT_TDM_RX_0 Audio Mixer", "MultiMedia15", "MM_DL15"}, {"TERT_TDM_RX_0 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"TERT_TDM_RX_0 Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"TERT_TDM_RX_0 Audio Mixer", "MultiMedia22", "MM_DL22"}, {"TERT_TDM_RX_0 Audio Mixer", "MultiMedia26", "MM_DL26"}, {"TERT_TDM_RX_0", NULL, "TERT_TDM_RX_0 Audio Mixer"}, @@ -14014,6 +14074,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"TERT_TDM_RX_1 Audio Mixer", "MultiMedia15", "MM_DL15"}, {"TERT_TDM_RX_1 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"TERT_TDM_RX_1 Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"TERT_TDM_RX_1 Audio Mixer", "MultiMedia22", "MM_DL22"}, {"TERT_TDM_RX_1 Audio Mixer", "MultiMedia26", "MM_DL26"}, {"TERT_TDM_RX_1", NULL, "TERT_TDM_RX_1 Audio Mixer"}, @@ -14034,6 +14095,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"TERT_TDM_RX_2 Audio Mixer", "MultiMedia15", "MM_DL15"}, {"TERT_TDM_RX_2 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"TERT_TDM_RX_2 Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"TERT_TDM_RX_2 Audio Mixer", "MultiMedia22", "MM_DL22"}, {"TERT_TDM_RX_2 Audio Mixer", "MultiMedia26", "MM_DL26"}, {"TERT_TDM_RX_2", NULL, "TERT_TDM_RX_2 Audio Mixer"}, @@ -14054,6 +14116,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"TERT_TDM_RX_3 Audio Mixer", "MultiMedia15", "MM_DL15"}, {"TERT_TDM_RX_3 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"TERT_TDM_RX_3 Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"TERT_TDM_RX_3 Audio Mixer", "MultiMedia22", "MM_DL22"}, {"TERT_TDM_RX_3 Audio Mixer", "MultiMedia26", "MM_DL26"}, {"TERT_TDM_RX_3", NULL, "TERT_TDM_RX_3 Audio Mixer"}, @@ -14074,6 +14137,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia15", "MM_DL15"}, {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia22", "MM_DL22"}, {"TERT_TDM_RX_4 Audio Mixer", "MultiMedia26", "MM_DL26"}, {"TERT_TDM_RX_4", NULL, "TERT_TDM_RX_4 Audio Mixer"}, @@ -14095,47 +14159,10 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_TDM_RX_0 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"QUAT_TDM_RX_0 Audio Mixer", "MultiMedia20", "MM_DL20"}, {"QUAT_TDM_RX_0 Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"QUAT_TDM_RX_0 Audio Mixer", "MultiMedia22", "MM_DL22"}, {"QUAT_TDM_RX_0 Audio Mixer", "MultiMedia26", "MM_DL26"}, {"QUAT_TDM_RX_0", NULL, "QUAT_TDM_RX_0 Audio Mixer"}, - {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia1", "MM_DL1"}, - {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia2", "MM_DL2"}, - {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia3", "MM_DL3"}, - {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia4", "MM_DL4"}, - {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia5", "MM_DL5"}, - {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia6", "MM_DL6"}, - {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia7", "MM_DL7"}, - {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia8", "MM_DL8"}, - {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia9", "MM_DL9"}, - {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia10", "MM_DL10"}, - {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia11", "MM_DL11"}, - {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia12", "MM_DL12"}, - {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia13", "MM_DL13"}, - {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia14", "MM_DL14"}, - {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia15", "MM_DL15"}, - {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia16", "MM_DL16"}, - {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia26", "MM_DL26"}, - {"PRI_TDM_RX_0", NULL, "PRI_TDM_RX_0 Audio Mixer"}, - - {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia1", "MM_DL1"}, - {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia2", "MM_DL2"}, - {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia3", "MM_DL3"}, - {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia4", "MM_DL4"}, - {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia5", "MM_DL5"}, - {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia6", "MM_DL6"}, - {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia7", "MM_DL7"}, - {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia8", "MM_DL8"}, - {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia9", "MM_DL9"}, - {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia10", "MM_DL10"}, - {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia11", "MM_DL11"}, - {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia12", "MM_DL12"}, - {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia13", "MM_DL13"}, - {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia14", "MM_DL14"}, - {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia15", "MM_DL15"}, - {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia16", "MM_DL16"}, - {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia26", "MM_DL26"}, - {"SEC_TDM_RX_0", NULL, "SEC_TDM_RX_0 Audio Mixer"}, - {"QUAT_TDM_TX_0 Audio Mixer", "MultiMedia1", "MM_DL1"}, {"QUAT_TDM_TX_0 Audio Mixer", "MultiMedia2", "MM_DL2"}, {"QUAT_TDM_TX_0 Audio Mixer", "MultiMedia3", "MM_DL3"}, @@ -14172,6 +14199,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_TDM_RX_1 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"QUAT_TDM_RX_1 Audio Mixer", "MultiMedia20", "MM_DL20"}, {"QUAT_TDM_RX_1 Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"QUAT_TDM_RX_1 Audio Mixer", "MultiMedia22", "MM_DL22"}, {"QUAT_TDM_RX_1 Audio Mixer", "MultiMedia26", "MM_DL26"}, {"QUAT_TDM_RX_1", NULL, "QUAT_TDM_RX_1 Audio Mixer"}, @@ -14193,6 +14221,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_TDM_RX_2 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"QUAT_TDM_RX_2 Audio Mixer", "MultiMedia20", "MM_DL20"}, {"QUAT_TDM_RX_2 Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"QUAT_TDM_RX_2 Audio Mixer", "MultiMedia22", "MM_DL22"}, {"QUAT_TDM_RX_2 Audio Mixer", "MultiMedia26", "MM_DL26"}, {"QUAT_TDM_RX_2", NULL, "QUAT_TDM_RX_2 Audio Mixer"}, @@ -14214,6 +14243,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_TDM_RX_3 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"QUAT_TDM_RX_3 Audio Mixer", "MultiMedia20", "MM_DL20"}, {"QUAT_TDM_RX_3 Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"QUAT_TDM_RX_3 Audio Mixer", "MultiMedia22", "MM_DL22"}, {"QUAT_TDM_RX_3 Audio Mixer", "MultiMedia26", "MM_DL26"}, {"QUAT_TDM_RX_3", NULL, "QUAT_TDM_RX_3 Audio Mixer"}, diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c index 4b76f1b8af1d..24d4199ac30b 100644 --- a/sound/soc/msm/qdsp6v2/q6adm.c +++ b/sound/soc/msm/qdsp6v2/q6adm.c @@ -454,7 +454,7 @@ int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id, int channel_index) { struct adm_cmd_set_pspd_mtmx_strtr_params_v5 *adm_params = NULL; - struct param_hdr_v3 data_v5 = {0,}; + struct param_hdr_v1 data_v5 = {0,}; int ret = 0, port_idx, sz = 0, param_size = 0; u16 *adm_pspd_params; u16 *ptr; @@ -511,7 +511,7 @@ int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id, data_v5.param_size = param_size; adm_params->payload_size = sizeof(struct default_chmixer_param_id_coeff) + - sizeof(struct param_hdr_v3) + data_v5.param_size; + sizeof(struct param_hdr_v1) + data_v5.param_size; adm_pspd_params = (u16 *)((u8 *)adm_params + sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5)); memcpy(adm_pspd_params, &data_v5, sizeof(data_v5)); diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c index 352ea9257832..84ab632d9b9c 100644 --- a/sound/soc/msm/qdsp6v2/q6afe.c +++ b/sound/soc/msm/qdsp6v2/q6afe.c @@ -178,6 +178,42 @@ done: return ret; } +static atomic_t tdm_gp_en_ref[IDX_GROUP_TDM_MAX]; + +static int afe_get_tdm_group_idx(u16 group_id) +{ + int gp_idx = -1; + + switch (group_id) { + case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_RX: + gp_idx = IDX_GROUP_PRIMARY_TDM_RX; + break; + case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_TX: + gp_idx = IDX_GROUP_PRIMARY_TDM_TX; + break; + case AFE_GROUP_DEVICE_ID_SECONDARY_TDM_RX: + gp_idx = IDX_GROUP_SECONDARY_TDM_RX; + break; + case AFE_GROUP_DEVICE_ID_SECONDARY_TDM_TX: + gp_idx = IDX_GROUP_SECONDARY_TDM_TX; + break; + case AFE_GROUP_DEVICE_ID_TERTIARY_TDM_RX: + gp_idx = IDX_GROUP_TERTIARY_TDM_RX; + break; + case AFE_GROUP_DEVICE_ID_TERTIARY_TDM_TX: + gp_idx = IDX_GROUP_TERTIARY_TDM_TX; + break; + case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_RX: + gp_idx = IDX_GROUP_QUATERNARY_TDM_RX; + break; + case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_TX: + gp_idx = IDX_GROUP_QUATERNARY_TDM_TX; + break; + } + + return gp_idx; +} + int afe_get_topology(int port_id) { int topology; @@ -356,6 +392,7 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv) return -EINVAL; } if (data->opcode == RESET_EVENTS) { + int i = 0; pr_debug("%s: reset event = %d %d apr[%pK]\n", __func__, data->reset_event, data->reset_proc, this_afe.apr); @@ -398,6 +435,12 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv) this_afe.rx_cb = NULL; } + /* + * reset TDM group enable ref cnt + */ + for (i = 0; i < IDX_GROUP_TDM_MAX; i++) + atomic_set(&tdm_gp_en_ref[i], 0); + return 0; } afe_callback_debug_print(data); @@ -3864,11 +3907,36 @@ int afe_port_group_enable(u16 group_id, { struct afe_group_device_enable group_enable = {0}; struct param_hdr_v3 param_hdr = {0}; - int ret; + int ret = 0; + int gp_idx; pr_debug("%s: group id: 0x%x enable: %d\n", __func__, group_id, enable); + gp_idx = afe_get_tdm_group_idx(group_id); + + if ((gp_idx >= 0) && (gp_idx < IDX_GROUP_TDM_MAX)) { + + atomic_t *gp_ref = &tdm_gp_en_ref[gp_idx]; + + if (enable) + atomic_inc(gp_ref); + else + atomic_dec(gp_ref); + + if ((enable) && (atomic_read(gp_ref) > 1)) { + pr_err("%s: this TDM group is enabled already %d refs_cnt %d\n", + __func__, group_id, atomic_read(gp_ref)); + goto rtn; + } + + if ((!enable) && (atomic_read(gp_ref) > 0)) { + pr_err("%s: this TDM group will be disabled in last call %d refs_cnt %d\n", + __func__, group_id, atomic_read(gp_ref)); + goto rtn; + } + } + ret = afe_q6_interface_prepare(); if (ret != 0) { pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret); @@ -3896,6 +3964,8 @@ int afe_port_group_enable(u16 group_id, pr_err("%s: AFE_PARAM_ID_GROUP_DEVICE_ENABLE failed %d\n", __func__, ret); +rtn: + return ret; } @@ -6556,6 +6626,10 @@ static int __init afe_init(void) pr_err("%s: could not init cal data! %d\n", __func__, ret); config_debug_fs_init(); + + for (i = 0; i < IDX_GROUP_TDM_MAX; i++) + atomic_set(&tdm_gp_en_ref[i], 0); + return 0; } |
