summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt6
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-mdss-pll.dtsi7
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-mdss.dtsi15
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-qrd.dtsi12
-rw-r--r--arch/arm/boot/dts/qcom/sdm630.dtsi7
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-mdss-pll.dtsi13
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-mdss.dtsi28
-rw-r--r--arch/arm/boot/dts/qcom/sdm660.dtsi7
-rw-r--r--arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-ivi-la.dts1
-rw-r--r--drivers/gpu/msm/kgsl.c39
-rw-r--r--drivers/i2c/busses/i2c-msm-v2.c6
-rw-r--r--drivers/net/wireless/cnss2/main.c40
-rw-r--r--drivers/net/wireless/cnss2/pci.c88
-rw-r--r--drivers/net/wireless/cnss2/wlan_firmware_service_v01.c101
-rw-r--r--drivers/net/wireless/cnss2/wlan_firmware_service_v01.h15
-rw-r--r--drivers/net/wireless/wcnss/wcnss_wlan.c6
-rw-r--r--drivers/soc/qcom/hab/hab.c58
-rw-r--r--drivers/soc/qcom/hab/hab.h9
-rw-r--r--drivers/soc/qcom/hab/hab_ghs.c96
-rw-r--r--drivers/soc/qcom/hab/hab_mem_linux.c443
-rw-r--r--drivers/soc/qcom/hab/hab_mimex.c5
-rw-r--r--drivers/soc/qcom/hab/hab_msg.c13
-rw-r--r--drivers/soc/qcom/hab/hab_open.c7
-rw-r--r--drivers/soc/qcom/hab/hab_vchan.c36
-rw-r--r--drivers/soc/qcom/qdsp6v2/audio-anc-dev-mgr.c69
-rw-r--r--drivers/soc/qcom/qdsp6v2/audio_anc.c17
-rw-r--r--drivers/soc/qcom/qdsp6v2/sdsp-anc.c243
-rw-r--r--drivers/soc/qcom/subsystem_notif_virt.c7
-rw-r--r--drivers/usb/misc/Kconfig15
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.c329
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.h6
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_panel.c46
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_phy.c31
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_phy.h4
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.c6
-rw-r--r--drivers/video/fbdev/msm/mdss_panel.h3
-rw-r--r--drivers/video/fbdev/msm/msm_mdss_io_8974.c103
-rw-r--r--fs/sdcardfs/main.c2
-rw-r--r--fs/sdcardfs/super.c2
-rw-r--r--include/linux/qdsp6v2/audio-anc-dev-mgr.h2
-rw-r--r--include/linux/qdsp6v2/sdsp_anc.h97
-rw-r--r--include/net/cnss2.h3
-rw-r--r--include/uapi/linux/habmmid.h8
-rw-r--r--include/uapi/linux/msm_audio_anc.h17
-rw-r--r--include/uapi/linux/msm_kgsl.h2
46 files changed, 1435 insertions, 638 deletions
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index cc55f6e2bfa0..4d0e1d5e12a2 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -165,6 +165,9 @@ Optional properties:
- qcom,mdss-dsi-border-color: Defines the border color value if border is present.
0 = default value.
- qcom,mdss-dsi-pan-enable-dynamic-fps: Boolean used to enable change in frame rate dynamically.
+- qcom,mdss-dsi-pan-enable-dynamic-bitclk: Boolean used to enable change in DSI clock dynamically.
+- qcom,mdss-dsi-dynamic-bitclk_freq: An array of integers that specifies the DSI bit clock
+ frequencies supported as part of dynamic bit clock feature.
- qcom,mdss-dsi-pan-fps-update: A string that specifies when to change the frame rate.
"dfps_suspend_resume_mode"= FPS change request is
implemented during suspend/resume.
@@ -696,6 +699,9 @@ Example:
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
qcom,mdss-dsi-pan-enable-dynamic-fps;
qcom,mdss-dsi-pan-fps-update = "dfps_suspend_resume_mode";
+ qcom,mdss-dsi-pan-enable-dynamic-bitclk;
+ qcom,mdss-dsi-dynamic-bitclk_freq = <711037824 724453632 737869440
+ 751285248 764701056 778116864 791532672 804948480>;
qcom,min-refresh-rate = <30>;
qcom,max-refresh-rate = <60>;
qcom,mdss-dsi-bl-pmic-bank-select = <0>;
diff --git a/arch/arm/boot/dts/qcom/sdm630-mdss-pll.dtsi b/arch/arm/boot/dts/qcom/sdm630-mdss-pll.dtsi
index 42eac0ab223a..3adf92a76347 100644
--- a/arch/arm/boot/dts/qcom/sdm630-mdss-pll.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-mdss-pll.dtsi
@@ -1,4 +1,4 @@
-/* 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
@@ -19,8 +19,9 @@
#clock-cells = <1>;
reg = <0xc994400 0x588>,
- <0xc8c2300 0x8>;
- reg-names = "pll_base", "gdsc_base";
+ <0xc8c2300 0x8>,
+ <0xc994200 0x98>;
+ reg-names = "pll_base", "gdsc_base", "dynamic_pll_base";
gdsc-supply = <&gdsc_mdss>;
diff --git a/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi b/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi
index d7fef426d4b6..de06a67db1b9 100644
--- a/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi
@@ -1,4 +1,4 @@
-/* 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
@@ -359,10 +359,19 @@
<&clock_mmss MMSS_MDSS_ESC0_CLK>,
<&clock_mmss BYTE0_CLK_SRC>,
<&clock_mmss PCLK0_CLK_SRC>,
- <&clock_mmss MMSS_MDSS_BYTE0_INTF_CLK>;
+ <&clock_mmss MMSS_MDSS_BYTE0_INTF_CLK>,
+ <&mdss_dsi0_pll BYTE0_MUX_CLK>,
+ <&mdss_dsi0_pll PIX0_MUX_CLK>,
+ <&mdss_dsi0_pll BYTE0_SRC_CLK>,
+ <&mdss_dsi0_pll PIX0_SRC_CLK>,
+ <&mdss_dsi0_pll SHADOW_BYTE0_SRC_CLK>,
+ <&mdss_dsi0_pll SHADOW_PIX0_SRC_CLK>;
clock-names = "byte_clk", "pixel_clk", "core_clk",
"byte_clk_rcg", "pixel_clk_rcg",
- "byte_intf_clk";
+ "byte_intf_clk", "pll_byte_clk_mux",
+ "pll_pixel_clk_mux", "pll_byte_clk_src",
+ "pll_pixel_clk_src", "pll_shadow_byte_clk_src",
+ "pll_shadow_pixel_clk_src";
qcom,platform-strength-ctrl = [ff 06
ff 06
diff --git a/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi b/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
index 384e24d221c4..82e80891e05d 100644
--- a/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
@@ -1,4 +1,4 @@
-/* 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
@@ -366,16 +366,6 @@
gpio-key,wakeup;
debounce-interval = <15>;
};
-
- home {
- label = "home";
- gpios = <&pm660_gpios 11 0x1>;
- linux,input-type = <1>;
- linux,code = <102>;
- gpio-key,wakeup;
- debounce-interval = <15>;
- };
-
};
hbtp {
diff --git a/arch/arm/boot/dts/qcom/sdm630.dtsi b/arch/arm/boot/dts/qcom/sdm630.dtsi
index 1e767b4648b1..808421c763ea 100644
--- a/arch/arm/boot/dts/qcom/sdm630.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630.dtsi
@@ -406,9 +406,14 @@
};
cont_splash_mem: splash_region@9d400000 {
- reg = <0x0 0x9d400000 0x0 0x02400000>;
+ reg = <0x0 0x9d400000 0x0 0x23ff000>;
label = "cont_splash_mem";
};
+
+ dfps_data_mem: dfps_data_mem@0x9f7ff000 {
+ reg = <0 0x9f7ff000 0 0x00001000>;
+ label = "dfps_data_mem";
+ };
};
bluetooth: bt_wcn3990 {
diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
index b2f4a8ce47d3..6abd62c01fb5 100644
--- a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
@@ -144,6 +144,9 @@
qcom,mdss-dsi-panel-max-error-count = <3>;
qcom,mdss-dsi-min-refresh-rate = <53>;
qcom,mdss-dsi-max-refresh-rate = <60>;
+ qcom,mdss-dsi-pan-enable-dynamic-bitclk;
+ qcom,mdss-dsi-dynamic-bitclk_freq = <798240576 801594528 804948480
+ 808302432 811656384>;
qcom,mdss-dsi-pan-enable-dynamic-fps;
qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
};
diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss-pll.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss-pll.dtsi
index 69d3736d4ba8..a3b6aadd893e 100644
--- a/arch/arm/boot/dts/qcom/sdm660-mdss-pll.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-mdss-pll.dtsi
@@ -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
@@ -19,8 +19,9 @@
#clock-cells = <1>;
reg = <0xc994400 0x588>,
- <0xc8c2300 0x8>;
- reg-names = "pll_base", "gdsc_base";
+ <0xc8c2300 0x8>,
+ <0xc994200 0x98>;
+ reg-names = "pll_base", "gdsc_base", "dynamic_pll_base";
gdsc-supply = <&gdsc_mdss>;
@@ -29,6 +30,7 @@
clock-rate = <0>;
qcom,dsi-pll-ssc-en;
qcom,dsi-pll-ssc-mode = "down-spread";
+ memory-region = <&dfps_data_mem>;
qcom,platform-supply-entries {
#address-cells = <1>;
@@ -54,8 +56,9 @@
#clock-cells = <1>;
reg = <0xc996400 0x588>,
- <0xc8c2300 0x8>;
- reg-names = "pll_base", "gdsc_base";
+ <0xc8c2300 0x8>,
+ <0xc996200 0x98>;
+ reg-names = "pll_base", "gdsc_base", "dynamic_pll_base";
gdsc-supply = <&gdsc_mdss>;
diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi
index ab4e71e3cd65..b4fbb23c51e4 100644
--- a/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi
@@ -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
@@ -382,10 +382,19 @@
<&clock_mmss MMSS_MDSS_ESC0_CLK>,
<&clock_mmss BYTE0_CLK_SRC>,
<&clock_mmss PCLK0_CLK_SRC>,
- <&clock_mmss MMSS_MDSS_BYTE0_INTF_CLK>;
+ <&clock_mmss MMSS_MDSS_BYTE0_INTF_CLK>,
+ <&mdss_dsi0_pll BYTE0_MUX_CLK>,
+ <&mdss_dsi0_pll PIX0_MUX_CLK>,
+ <&mdss_dsi0_pll BYTE0_SRC_CLK>,
+ <&mdss_dsi0_pll PIX0_SRC_CLK>,
+ <&mdss_dsi0_pll SHADOW_BYTE0_SRC_CLK>,
+ <&mdss_dsi0_pll SHADOW_PIX0_SRC_CLK>;
clock-names = "byte_clk", "pixel_clk", "core_clk",
"byte_clk_rcg", "pixel_clk_rcg",
- "byte_intf_clk";
+ "byte_intf_clk", "pll_byte_clk_mux",
+ "pll_pixel_clk_mux", "pll_byte_clk_src",
+ "pll_pixel_clk_src", "pll_shadow_byte_clk_src",
+ "pll_shadow_pixel_clk_src";
qcom,null-insertion-enabled;
qcom,platform-strength-ctrl = [ff 06
@@ -423,10 +432,19 @@
<&clock_mmss MMSS_MDSS_ESC1_CLK>,
<&clock_mmss BYTE1_CLK_SRC>,
<&clock_mmss PCLK1_CLK_SRC>,
- <&clock_mmss MMSS_MDSS_BYTE1_INTF_CLK>;
+ <&clock_mmss MMSS_MDSS_BYTE1_INTF_CLK>,
+ <&mdss_dsi1_pll BYTE1_MUX_CLK>,
+ <&mdss_dsi1_pll PIX1_MUX_CLK>,
+ <&mdss_dsi1_pll BYTE1_SRC_CLK>,
+ <&mdss_dsi1_pll PIX1_SRC_CLK>,
+ <&mdss_dsi1_pll SHADOW_BYTE1_SRC_CLK>,
+ <&mdss_dsi1_pll SHADOW_PIX1_SRC_CLK>;
clock-names = "byte_clk", "pixel_clk", "core_clk",
"byte_clk_rcg", "pixel_clk_rcg",
- "byte_intf_clk";
+ "byte_intf_clk", "pll_byte_clk_mux",
+ "pll_pixel_clk_mux", "pll_byte_clk_src",
+ "pll_pixel_clk_src", "pll_shadow_byte_clk_src",
+ "pll_shadow_pixel_clk_src";
qcom,null-insertion-enabled;
qcom,platform-strength-ctrl = [ff 06
diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi
index ef72d6bed86f..27bc0cebfc2a 100644
--- a/arch/arm/boot/dts/qcom/sdm660.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660.dtsi
@@ -404,9 +404,14 @@
};
cont_splash_mem: splash_region@9d400000 {
- reg = <0x0 0x9d400000 0x0 0x02400000>;
+ reg = <0x0 0x9d400000 0x0 0x23ff000>;
label = "cont_splash_mem";
};
+
+ dfps_data_mem: dfps_data_mem@0x9f7ff000 {
+ reg = <0 0x9f7ff000 0 0x00001000>;
+ label = "dfps_data_mem";
+ };
};
bluetooth: bt_wcn3990 {
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 3434514df69c..5856aa1f6447 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
@@ -140,6 +140,7 @@
pinctrl-names = "bootstrap_active", "bootstrap_sleep";
pinctrl-0 = <&cnss_bootstrap_active>;
pinctrl-1 = <&cnss_bootstrap_sleep>;
+ qcom,wlan-ramdump-dynamic = <0x200000>;
qcom,msm-bus,name = "msm-cnss";
qcom,msm-bus,num-cases = <4>;
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 02f0cb7eb16c..55ebc0a8e26c 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1403,6 +1403,45 @@ long kgsl_ioctl_device_getproperty(struct kgsl_device_private *dev_priv,
kgsl_context_put(context);
break;
}
+ case KGSL_PROP_SECURE_BUFFER_ALIGNMENT:
+ {
+ unsigned int align;
+
+ if (param->sizebytes != sizeof(unsigned int)) {
+ result = -EINVAL;
+ break;
+ }
+ /*
+ * XPUv2 impose the constraint of 1MB memory alignment,
+ * on the other hand Hypervisor does not have such
+ * constraints. So driver should fulfill such
+ * requirements when allocating secure memory.
+ */
+ align = MMU_FEATURE(&dev_priv->device->mmu,
+ KGSL_MMU_HYP_SECURE_ALLOC) ? PAGE_SIZE : SZ_1M;
+
+ if (copy_to_user(param->value, &align, sizeof(align)))
+ result = -EFAULT;
+
+ break;
+ }
+ case KGSL_PROP_SECURE_CTXT_SUPPORT:
+ {
+ unsigned int secure_ctxt;
+
+ if (param->sizebytes != sizeof(unsigned int)) {
+ result = -EINVAL;
+ break;
+ }
+
+ secure_ctxt = dev_priv->device->mmu.secured ? 1 : 0;
+
+ if (copy_to_user(param->value, &secure_ctxt,
+ sizeof(secure_ctxt)))
+ result = -EFAULT;
+
+ break;
+ }
default:
if (is_compat_task())
result = dev_priv->device->ftbl->getproperty_compat(
diff --git a/drivers/i2c/busses/i2c-msm-v2.c b/drivers/i2c/busses/i2c-msm-v2.c
index d72953f2df23..198e55829226 100644
--- a/drivers/i2c/busses/i2c-msm-v2.c
+++ b/drivers/i2c/busses/i2c-msm-v2.c
@@ -2330,6 +2330,12 @@ i2c_msm_frmwrk_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
struct i2c_msm_ctrl *ctrl = i2c_get_adapdata(adap);
struct i2c_msm_xfer *xfer = &ctrl->xfer;
+ if (num < 1) {
+ dev_err(ctrl->dev,
+ "error on number of msgs(%d) received\n", num);
+ return -EINVAL;
+ }
+
if (IS_ERR_OR_NULL(msgs)) {
dev_err(ctrl->dev, " error on msgs Accessing invalid pointer location\n");
return PTR_ERR(msgs);
diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c
index 8aa9eabdc73f..ac9d8e7d08ad 100644
--- a/drivers/net/wireless/cnss2/main.c
+++ b/drivers/net/wireless/cnss2/main.c
@@ -37,6 +37,7 @@
#define FW_READY_TIMEOUT 20000
#define FW_ASSERT_TIMEOUT 5000
#define CNSS_EVENT_PENDING 2989
+#define CE_MSI_NAME "CE"
static struct cnss_plat_data *plat_env;
@@ -249,7 +250,7 @@ int cnss_wlan_enable(struct device *dev,
{
struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
struct wlfw_wlan_cfg_req_msg_v01 req;
- u32 i;
+ u32 i, ce_id, num_vectors, user_base_data, base_vector;
int ret = 0;
if (plat_priv->device_id == QCA6174_DEVICE_ID)
@@ -299,6 +300,19 @@ int cnss_wlan_enable(struct device *dev,
req.svc_cfg[i].pipe_num = config->ce_svc_cfg[i].pipe_num;
}
+ if (config->num_shadow_reg_cfg) {
+ req.shadow_reg_valid = 1;
+
+ if (config->num_shadow_reg_cfg >
+ QMI_WLFW_MAX_NUM_SHADOW_REG_V01)
+ req.shadow_reg_len = QMI_WLFW_MAX_NUM_SHADOW_REG_V01;
+ else
+ req.shadow_reg_len = config->num_shadow_reg_cfg;
+ memcpy(req.shadow_reg, config->shadow_reg_cfg,
+ sizeof(struct wlfw_shadow_reg_cfg_s_v01)
+ * req.shadow_reg_len);
+ }
+
req.shadow_reg_v2_valid = 1;
if (config->num_shadow_reg_v2_cfg >
QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01)
@@ -310,6 +324,30 @@ int cnss_wlan_enable(struct device *dev,
sizeof(struct wlfw_shadow_reg_v2_cfg_s_v01)
* req.shadow_reg_v2_len);
+ if (config->rri_over_ddr_cfg_valid) {
+ req.rri_over_ddr_cfg_valid = 1;
+ req.rri_over_ddr_cfg.base_addr_low =
+ config->rri_over_ddr_cfg.base_addr_low;
+ req.rri_over_ddr_cfg.base_addr_high =
+ config->rri_over_ddr_cfg.base_addr_high;
+ }
+
+ if (plat_priv->device_id == QCN7605_DEVICE_ID) {
+ ret = cnss_get_user_msi_assignment(dev, CE_MSI_NAME,
+ &num_vectors,
+ &user_base_data,
+ &base_vector);
+ if (!ret) {
+ req.msi_cfg_valid = 1;
+ req.msi_cfg_len = QMI_WLFW_MAX_NUM_CE_V01;
+ for (ce_id = 0; ce_id < QMI_WLFW_MAX_NUM_CE_V01;
+ ce_id++) {
+ req.msi_cfg[ce_id].ce_id = ce_id;
+ req.msi_cfg[ce_id].msi_vector =
+ (ce_id % num_vectors) + base_vector;
+ }
+ }
+ }
ret = cnss_wlfw_wlan_cfg_send_sync(plat_priv, &req);
if (ret)
goto out;
diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c
index 1d4b5b9ea9c9..427b42c871f3 100644
--- a/drivers/net/wireless/cnss2/pci.c
+++ b/drivers/net/wireless/cnss2/pci.c
@@ -1297,6 +1297,94 @@ int cnss_pm_request_resume(struct cnss_pci_data *pci_priv)
return pm_request_resume(&pci_dev->dev);
}
+#ifdef CONFIG_CNSS_QCA6390
+int cnss_pci_force_wake_request(struct device *dev)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
+ struct mhi_controller *mhi_ctrl;
+
+ if (!pci_priv)
+ return -ENODEV;
+
+ if (pci_priv->device_id != QCA6390_DEVICE_ID)
+ return 0;
+
+ mhi_ctrl = pci_priv->mhi_ctrl;
+ if (!mhi_ctrl)
+ return -EINVAL;
+
+ read_lock_bh(&mhi_ctrl->pm_lock);
+ mhi_ctrl->wake_get(mhi_ctrl, true);
+ read_unlock_bh(&mhi_ctrl->pm_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(cnss_pci_force_wake_request);
+
+int cnss_pci_is_device_awake(struct device *dev)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
+ struct mhi_controller *mhi_ctrl;
+
+ if (!pci_priv)
+ return -ENODEV;
+
+ if (pci_priv->device_id != QCA6390_DEVICE_ID)
+ return true;
+
+ mhi_ctrl = pci_priv->mhi_ctrl;
+ if (!mhi_ctrl)
+ return -EINVAL;
+
+ return mhi_ctrl->dev_state == MHI_STATE_M0 ? true : false;
+}
+EXPORT_SYMBOL(cnss_pci_is_device_awake);
+
+int cnss_pci_force_wake_release(struct device *dev)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
+ struct mhi_controller *mhi_ctrl;
+
+ if (!pci_priv)
+ return -ENODEV;
+
+ if (pci_priv->device_id != QCA6390_DEVICE_ID)
+ return 0;
+
+ mhi_ctrl = pci_priv->mhi_ctrl;
+ if (!mhi_ctrl)
+ return -EINVAL;
+
+ read_lock_bh(&mhi_ctrl->pm_lock);
+ mhi_ctrl->wake_put(mhi_ctrl, false);
+ read_unlock_bh(&mhi_ctrl->pm_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(cnss_pci_force_wake_release);
+#else
+int cnss_pci_force_wake_request(struct device *dev)
+{
+ return 0;
+}
+EXPORT_SYMBOL(cnss_pci_force_wake_request);
+
+int cnss_pci_is_device_awake(struct device *dev)
+{
+ return true;
+}
+EXPORT_SYMBOL(cnss_pci_is_device_awake);
+
+int cnss_pci_force_wake_release(struct device *dev)
+{
+ return 0;
+}
+EXPORT_SYMBOL(cnss_pci_force_wake_release);
+#endif
+
int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv)
{
struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
diff --git a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c
index bbf707b869bd..8f2637c3eaf9 100644
--- a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c
+++ b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c
@@ -144,6 +144,60 @@ static struct elem_info wlfw_shadow_reg_v2_cfg_s_v01_ei[] = {
},
};
+static struct elem_info wlfw_rri_over_ddr_cfg_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_rri_over_ddr_cfg_s_v01,
+ base_addr_low),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u32),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct
+ wlfw_rri_over_ddr_cfg_s_v01,
+ base_addr_high),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+static struct elem_info wlfw_msi_cfg_s_v01_ei[] = {
+ {
+ .data_type = QMI_UNSIGNED_2_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u16),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_msi_cfg_s_v01,
+ ce_id),
+ },
+ {
+ .data_type = QMI_UNSIGNED_2_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u16),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_msi_cfg_s_v01,
+ msi_vector),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ },
+};
+
static struct elem_info wlfw_memory_region_info_s_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_8_BYTE,
@@ -922,6 +976,53 @@ struct elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = {
.ei_array = wlfw_shadow_reg_v2_cfg_s_v01_ei,
},
{
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x15,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ rri_over_ddr_cfg_valid),
+ },
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct wlfw_rri_over_ddr_cfg_s_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x15,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ rri_over_ddr_cfg),
+ .ei_array = wlfw_rri_over_ddr_cfg_s_v01_ei,
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x16,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ msi_cfg_valid),
+ },
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x16,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ msi_cfg_len),
+ },
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = QMI_WLFW_MAX_NUM_CE_V01,
+ .elem_size = sizeof(struct wlfw_msi_cfg_s_v01),
+ .is_array = VAR_LEN_ARRAY,
+ .tlv_type = 0x16,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ msi_cfg),
+ .ei_array = wlfw_msi_cfg_s_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 00a873d11d14..964c1e56dbdd 100644
--- a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h
+++ b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h
@@ -170,6 +170,16 @@ struct wlfw_shadow_reg_v2_cfg_s_v01 {
u32 addr;
};
+struct wlfw_rri_over_ddr_cfg_s_v01 {
+ u32 base_addr_low;
+ u32 base_addr_high;
+};
+
+struct wlfw_msi_cfg_s_v01 {
+ u16 ce_id;
+ u16 msi_vector;
+};
+
struct wlfw_memory_region_info_s_v01 {
u64 region_addr;
u32 size;
@@ -312,6 +322,11 @@ struct wlfw_wlan_cfg_req_msg_v01 {
u32 shadow_reg_v2_len;
struct wlfw_shadow_reg_v2_cfg_s_v01
shadow_reg_v2[QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01];
+ u8 rri_over_ddr_cfg_valid;
+ struct wlfw_rri_over_ddr_cfg_s_v01 rri_over_ddr_cfg;
+ u8 msi_cfg_valid;
+ u32 msi_cfg_len;
+ struct wlfw_msi_cfg_s_v01 msi_cfg[QMI_WLFW_MAX_NUM_CE_V01];
};
#define WLFW_WLAN_CFG_REQ_MSG_V01_MAX_MSG_LEN 803
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 13ae5c3c2471..b97e550cba5d 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -2368,6 +2368,12 @@ static void wcnss_nvbin_dnld(void)
goto out;
}
+ if (nv->size <= 4) {
+ pr_err("wcnss: %s: request_firmware failed for %s (file size = %zu)\n",
+ __func__, NVBIN_FILE, nv->size);
+ goto out;
+ }
+
/* First 4 bytes in nv blob is validity bitmap.
* We cannot validate nv, so skip those 4 bytes.
*/
diff --git a/drivers/soc/qcom/hab/hab.c b/drivers/soc/qcom/hab/hab.c
index db4961f5f15f..ebe7dfc4a5b6 100644
--- a/drivers/soc/qcom/hab/hab.c
+++ b/drivers/soc/qcom/hab/hab.c
@@ -21,7 +21,7 @@
.openlock = __SPIN_LOCK_UNLOCKED(&hab_devices[__num__].openlock)\
}
-static const char hab_info_str[] = "Change: 16764735 Revision: #76";
+static const char hab_info_str[] = "Change: 17280941 Revision: #81";
/*
* The following has to match habmm definitions, order does not matter if
@@ -42,15 +42,13 @@ static struct hab_device hab_devices[] = {
HAB_DEVICE_CNSTR(DEVICE_DISP5_NAME, MM_DISP_5, 10),
HAB_DEVICE_CNSTR(DEVICE_GFX_NAME, MM_GFX, 11),
HAB_DEVICE_CNSTR(DEVICE_VID_NAME, MM_VID, 12),
- HAB_DEVICE_CNSTR(DEVICE_MISC_NAME, MM_MISC, 13),
- HAB_DEVICE_CNSTR(DEVICE_QCPE1_NAME, MM_QCPE_VM1, 14),
- HAB_DEVICE_CNSTR(DEVICE_QCPE2_NAME, MM_QCPE_VM2, 15),
- HAB_DEVICE_CNSTR(DEVICE_QCPE3_NAME, MM_QCPE_VM3, 16),
- HAB_DEVICE_CNSTR(DEVICE_QCPE4_NAME, MM_QCPE_VM4, 17),
- HAB_DEVICE_CNSTR(DEVICE_CLK1_NAME, MM_CLK_VM1, 18),
- HAB_DEVICE_CNSTR(DEVICE_CLK2_NAME, MM_CLK_VM2, 19),
- HAB_DEVICE_CNSTR(DEVICE_FDE1_NAME, MM_FDE_1, 20),
- HAB_DEVICE_CNSTR(DEVICE_BUFFERQ1_NAME, MM_BUFFERQ_1, 21),
+ HAB_DEVICE_CNSTR(DEVICE_VID2_NAME, MM_VID_2, 13),
+ HAB_DEVICE_CNSTR(DEVICE_MISC_NAME, MM_MISC, 14),
+ HAB_DEVICE_CNSTR(DEVICE_QCPE1_NAME, MM_QCPE_VM1, 15),
+ HAB_DEVICE_CNSTR(DEVICE_CLK1_NAME, MM_CLK_VM1, 16),
+ HAB_DEVICE_CNSTR(DEVICE_CLK2_NAME, MM_CLK_VM2, 17),
+ HAB_DEVICE_CNSTR(DEVICE_FDE1_NAME, MM_FDE_1, 18),
+ HAB_DEVICE_CNSTR(DEVICE_BUFFERQ1_NAME, MM_BUFFERQ_1, 19),
};
struct hab_driver hab_driver = {
@@ -218,7 +216,15 @@ struct virtual_channel *hab_get_vchan_fromvcid(int32_t vcid,
read_lock(&ctx->ctx_lock);
list_for_each_entry(vchan, &ctx->vchannels, node) {
if (vcid == vchan->id) {
- kref_get(&vchan->refcount);
+ if (vchan->otherend_closed || vchan->closed ||
+ !kref_get_unless_zero(&vchan->refcount)) {
+ pr_debug("failed to inc vcid %x remote %x session %d refcnt %d close_flg remote %d local %d\n",
+ vchan->id, vchan->otherend_id,
+ vchan->session_id,
+ get_refcnt(vchan->refcount),
+ vchan->otherend_closed, vchan->closed);
+ vchan = NULL;
+ }
read_unlock(&ctx->ctx_lock);
return vchan;
}
@@ -1074,15 +1080,25 @@ static int hab_release(struct inode *inodep, struct file *filep)
/* notify remote side on vchan closing */
list_for_each_entry_safe(vchan, tmp, &ctx->vchannels, node) {
list_del(&vchan->node); /* vchan is not in this ctx anymore */
- hab_vchan_stop_notify(vchan);
+
+ if (!vchan->closed) { /* locally hasn't closed yet */
+ if (!kref_get_unless_zero(&vchan->refcount)) {
+ pr_err("vchan %x %x refcnt %d mismanaged closed %d remote closed %d\n",
+ vchan->id,
+ vchan->otherend_id,
+ get_refcnt(vchan->refcount),
+ vchan->closed, vchan->otherend_closed);
+ continue; /* vchan is already being freed */
+ } else {
+ hab_vchan_stop_notify(vchan);
+ /* put for notify. shouldn't cause free */
+ hab_vchan_put(vchan);
+ }
+ } else
+ continue;
+
write_unlock(&ctx->ctx_lock);
- if (!vchan->closed) {
- pr_warn("potential leak vc %pK %x remote %x session %d refcnt %d\n",
- vchan, vchan->id, vchan->otherend_id,
- vchan->session_id,
- get_refcnt(vchan->refcount));
- hab_vchan_put(vchan); /* there is a lock inside */
- }
+ hab_vchan_put(vchan); /* there is a lock inside */
write_lock(&ctx->ctx_lock);
}
@@ -1316,7 +1332,6 @@ static int __init hab_init(void)
dev_t dev;
place_marker("M - HAB INIT Start");
-
result = alloc_chrdev_region(&hab_driver.major, 0, 1, "hab");
if (result < 0) {
@@ -1371,11 +1386,8 @@ static int __init hab_init(void)
} else
set_dma_ops(hab_driver.dev, &hab_dma_ops);
}
-
hab_stat_init(&hab_driver);
-
place_marker("M - HAB INIT End");
-
return result;
err:
diff --git a/drivers/soc/qcom/hab/hab.h b/drivers/soc/qcom/hab/hab.h
index c4e8eaa368e3..cbc049e89d63 100644
--- a/drivers/soc/qcom/hab/hab.h
+++ b/drivers/soc/qcom/hab/hab.h
@@ -45,6 +45,7 @@
#include <linux/reboot.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
+#include <linux/delay.h>
#include <soc/qcom/boot_stats.h>
enum hab_payload_type {
@@ -81,11 +82,9 @@ enum hab_payload_type {
#define DEVICE_DISP5_NAME "hab_disp5"
#define DEVICE_GFX_NAME "hab_ogles"
#define DEVICE_VID_NAME "hab_vid"
+#define DEVICE_VID2_NAME "hab_vid2"
#define DEVICE_MISC_NAME "hab_misc"
#define DEVICE_QCPE1_NAME "hab_qcpe_vm1"
-#define DEVICE_QCPE2_NAME "hab_qcpe_vm2"
-#define DEVICE_QCPE3_NAME "hab_qcpe_vm3"
-#define DEVICE_QCPE4_NAME "hab_qcpe_vm4"
#define DEVICE_CLK1_NAME "hab_clock_vm1"
#define DEVICE_CLK2_NAME "hab_clock_vm2"
#define DEVICE_FDE1_NAME "hab_fde1"
@@ -346,6 +345,8 @@ struct hab_driver {
};
struct virtual_channel {
+ struct list_head node; /* for ctx */
+ struct list_head pnode; /* for pchan */
/*
* refcount is used to track the references from hab core to the virtual
* channel such as references from physical channels,
@@ -354,8 +355,6 @@ struct virtual_channel {
struct kref refcount;
struct physical_channel *pchan;
struct uhab_context *ctx;
- struct list_head node; /* for ctx */
- struct list_head pnode; /* for pchan */
struct list_head rx_list;
wait_queue_head_t rx_queue;
spinlock_t rx_lock;
diff --git a/drivers/soc/qcom/hab/hab_ghs.c b/drivers/soc/qcom/hab/hab_ghs.c
index e743d9b00a66..a445aa1a6707 100644
--- a/drivers/soc/qcom/hab/hab_ghs.c
+++ b/drivers/soc/qcom/hab/hab_ghs.c
@@ -14,6 +14,7 @@
#include "hab.h"
#include "hab_ghs.h"
+#define GIPC_VM_SET_CNT 22
static const char * const dt_gipc_path_name[] = {
"testgipc1",
"testgipc2",
@@ -39,12 +40,41 @@ static const char * const dt_gipc_path_name[] = {
"testgipc22",
};
+
+/* same vmid assignment for all the vms. it should matches dt_gipc_path_name */
+int mmid_order[GIPC_VM_SET_CNT] = {
+ MM_AUD_1,
+ MM_AUD_2,
+ MM_AUD_3,
+ MM_AUD_4,
+ MM_CAM_1,
+ MM_CAM_2,
+ MM_DISP_1,
+ MM_DISP_2,
+ MM_DISP_3,
+ MM_DISP_4,
+ MM_DISP_5,
+ MM_GFX,
+ MM_VID,
+ MM_MISC,
+ MM_QCPE_VM1,
+ MM_VID_2, /* newly recycled */
+ 0,
+ 0,
+ MM_CLK_VM1,
+ MM_CLK_VM2,
+ MM_FDE_1,
+ MM_BUFFERQ_1,
+};
+
static struct ghs_vmm_plugin_info_s {
const char * const *dt_name;
+ int *mmid_dt_mapping;
int curr;
int probe_cnt;
} ghs_vmm_plugin_info = {
dt_gipc_path_name,
+ mmid_order,
0,
ARRAY_SIZE(dt_gipc_path_name),
};
@@ -59,6 +89,33 @@ static void ghs_irq_handler(void *cookie)
tasklet_schedule(&dev->task);
}
+static int get_dt_name_idx(int vmid_base, int mmid,
+ struct ghs_vmm_plugin_info_s *plugin_info)
+{
+ int idx = -1;
+ int i;
+
+ if (vmid_base < 0 || vmid_base > plugin_info->probe_cnt /
+ GIPC_VM_SET_CNT) {
+ pr_err("vmid %d overflow expected max %d\n", vmid_base,
+ plugin_info->probe_cnt / GIPC_VM_SET_CNT);
+ return idx;
+ }
+
+ for (i = 0; i < GIPC_VM_SET_CNT; i++) {
+ if (mmid == plugin_info->mmid_dt_mapping[i]) {
+ idx = vmid_base * GIPC_VM_SET_CNT + i;
+ if (idx > plugin_info->probe_cnt) {
+ pr_err("dt name idx %d overflow max %d\n",
+ idx, plugin_info->probe_cnt);
+ idx = -1;
+ }
+ break;
+ }
+ }
+ return idx;
+}
+
/* static struct physical_channel *habhyp_commdev_alloc(int id) */
int habhyp_commdev_alloc(void **commdev, int is_be, char *name, int vmid_remote,
struct hab_device *mmid_device)
@@ -67,6 +124,7 @@ int habhyp_commdev_alloc(void **commdev, int is_be, char *name, int vmid_remote,
struct physical_channel *pchan = NULL;
struct physical_channel **ppchan = (struct physical_channel **)commdev;
int ret = 0;
+ int dt_name_idx = 0;
if (ghs_vmm_plugin_info.curr > ghs_vmm_plugin_info.probe_cnt) {
pr_err("too many commdev alloc %d, supported is %d\n",
@@ -101,13 +159,25 @@ int habhyp_commdev_alloc(void **commdev, int is_be, char *name, int vmid_remote,
gvh_dn = of_find_node_by_path("/aliases");
if (gvh_dn) {
const char *ep_path = NULL;
- struct device_node *ep_dn;
+ struct device_node *ep_dn = NULL;
+
+ dt_name_idx = get_dt_name_idx(vmid_remote,
+ mmid_device->id,
+ &ghs_vmm_plugin_info);
+ if (dt_name_idx < 0) {
+ pr_err("failed to find %s for vmid %d ret %d\n",
+ mmid_device->name,
+ mmid_device->id,
+ dt_name_idx);
+ ret = -ENOENT;
+ goto err;
+ }
ret = of_property_read_string(gvh_dn,
- ghs_vmm_plugin_info.dt_name[ghs_vmm_plugin_info.curr],
- &ep_path);
+ ghs_vmm_plugin_info.dt_name[dt_name_idx],
+ &ep_path);
if (ret)
- pr_err("failed to read endpoint string ret %d\n",
+ pr_err("failed to read endpoint str ret %d\n",
ret);
of_node_put(gvh_dn);
@@ -117,22 +187,23 @@ int habhyp_commdev_alloc(void **commdev, int is_be, char *name, int vmid_remote,
of_node_put(ep_dn);
if (IS_ERR(dev->endpoint)) {
ret = PTR_ERR(dev->endpoint);
- pr_err("KGIPC alloc failed id: %d, ret: %d\n",
- ghs_vmm_plugin_info.curr, ret);
+ pr_err("alloc failed %d %s ret %d\n",
+ dt_name_idx, mmid_device->name,
+ ret);
goto err;
} else {
- pr_debug("gipc ep found for %d\n",
- ghs_vmm_plugin_info.curr);
+ pr_debug("gipc ep found for %d %s\n",
+ dt_name_idx, mmid_device->name);
}
} else {
- pr_err("of_parse_phandle failed id: %d\n",
- ghs_vmm_plugin_info.curr);
+ pr_err("of_parse_phandle failed id %d %s\n",
+ dt_name_idx, mmid_device->name);
ret = -ENOENT;
goto err;
}
} else {
- pr_err("of_find_compatible_node failed id: %d\n",
- ghs_vmm_plugin_info.curr);
+ pr_err("of_find_compatible_node failed id %d %s\n",
+ dt_name_idx, mmid_device->name);
ret = -ENOENT;
goto err;
}
@@ -149,6 +220,7 @@ int habhyp_commdev_alloc(void **commdev, int is_be, char *name, int vmid_remote,
pchan->hyp_data = (void *)dev;
pchan->is_be = is_be;
strlcpy(dev->name, name, sizeof(dev->name));
+ strlcpy(pchan->name, name, sizeof(pchan->name));
*ppchan = pchan;
dev->read_data = kmalloc(GIPC_RECV_BUFF_SIZE_BYTES, GFP_KERNEL);
if (!dev->read_data) {
diff --git a/drivers/soc/qcom/hab/hab_mem_linux.c b/drivers/soc/qcom/hab/hab_mem_linux.c
index b5afd983d64c..60156c6b00f0 100644
--- a/drivers/soc/qcom/hab/hab_mem_linux.c
+++ b/drivers/soc/qcom/hab/hab_mem_linux.c
@@ -21,18 +21,14 @@ struct pages_list {
struct page **pages;
long npages;
uint64_t index; /* for mmap first call */
- int kernel;
void *kva;
- void *uva;
- int refcntk;
- int refcntu;
uint32_t userflags;
struct file *filp_owner;
struct file *filp_mapper;
- struct dma_buf *dmabuf;
int32_t export_id;
int32_t vcid;
struct physical_channel *pchan;
+ struct kref refcount;
};
struct importer_context {
@@ -42,6 +38,118 @@ struct importer_context {
rwlock_t implist_lock;
};
+static struct pages_list *pages_list_create(
+ void *imp_ctx,
+ struct export_desc *exp,
+ uint32_t userflags)
+{
+ struct page **pages;
+ struct compressed_pfns *pfn_table =
+ (struct compressed_pfns *)exp->payload;
+ struct pages_list *pglist;
+ unsigned long pfn;
+ int i, j, k = 0, size;
+
+ if (!pfn_table)
+ return ERR_PTR(-EINVAL);
+
+ size = exp->payload_count * sizeof(struct page *);
+ pages = kmalloc(size, GFP_KERNEL);
+ if (!pages)
+ return ERR_PTR(-ENOMEM);
+
+ pglist = kzalloc(sizeof(*pglist), GFP_KERNEL);
+ if (!pglist) {
+ kfree(pages);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ 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;
+ }
+
+ pglist->pages = pages;
+ pglist->npages = exp->payload_count;
+ pglist->userflags = userflags;
+ pglist->export_id = exp->export_id;
+ pglist->vcid = exp->vcid_remote;
+ pglist->pchan = exp->pchan;
+
+ kref_init(&pglist->refcount);
+
+ return pglist;
+}
+
+static void pages_list_destroy(struct kref *refcount)
+{
+ struct pages_list *pglist = container_of(refcount,
+ struct pages_list, refcount);
+
+ if (pglist->kva)
+ vunmap(pglist->kva);
+
+ kfree(pglist->pages);
+
+ kfree(pglist);
+}
+
+static void pages_list_get(struct pages_list *pglist)
+{
+ kref_get(&pglist->refcount);
+}
+
+static int pages_list_put(struct pages_list *pglist)
+{
+ return kref_put(&pglist->refcount, pages_list_destroy);
+}
+
+static struct pages_list *pages_list_lookup(
+ struct importer_context *imp_ctx,
+ uint32_t export_id, struct physical_channel *pchan)
+{
+ struct pages_list *pglist, *tmp;
+
+ read_lock(&imp_ctx->implist_lock);
+ list_for_each_entry_safe(pglist, tmp, &imp_ctx->imp_list, list) {
+ if (pglist->export_id == export_id &&
+ pglist->pchan == pchan) {
+ pages_list_get(pglist);
+ read_unlock(&imp_ctx->implist_lock);
+ return pglist;
+ }
+ }
+ read_unlock(&imp_ctx->implist_lock);
+
+ return NULL;
+}
+
+static void pages_list_add(struct importer_context *imp_ctx,
+ struct pages_list *pglist)
+{
+ pages_list_get(pglist);
+
+ write_lock(&imp_ctx->implist_lock);
+ list_add_tail(&pglist->list, &imp_ctx->imp_list);
+ imp_ctx->cnt++;
+ write_unlock(&imp_ctx->implist_lock);
+}
+
+static void pages_list_remove(struct importer_context *imp_ctx,
+ struct pages_list *pglist)
+{
+ write_lock(&imp_ctx->implist_lock);
+ list_del(&pglist->list);
+ imp_ctx->cnt--;
+ write_unlock(&imp_ctx->implist_lock);
+
+ pages_list_put(pglist);
+}
+
void *habmm_hyp_allocate_grantable(int page_count,
uint32_t *sizebytes)
{
@@ -192,9 +300,12 @@ static int habmem_get_dma_pages_from_fd(int32_t fd,
for (j = 0; j < (s->length >> PAGE_SHIFT); j++) {
pages[rc] = nth_page(page, j);
rc++;
- if (WARN_ON(rc >= page_count))
+ if (rc >= page_count)
break;
}
+
+ if (rc >= page_count)
+ break;
}
err:
@@ -320,16 +431,8 @@ void habmem_imp_hyp_close(void *imp_ctx, int kernel)
if (!priv)
return;
- list_for_each_entry_safe(pglist, pglist_tmp, &priv->imp_list, list) {
- if (kernel && pglist->kva)
- vunmap(pglist->kva);
-
- list_del(&pglist->list);
- priv->cnt--;
-
- kfree(pglist->pages);
- kfree(pglist);
- }
+ list_for_each_entry_safe(pglist, pglist_tmp, &priv->imp_list, list)
+ pages_list_remove(priv, pglist);
kfree(priv);
}
@@ -406,10 +509,19 @@ static int hab_map_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
static void hab_map_open(struct vm_area_struct *vma)
{
+ struct pages_list *pglist =
+ (struct pages_list *)vma->vm_private_data;
+
+ pages_list_get(pglist);
}
static void hab_map_close(struct vm_area_struct *vma)
{
+ struct pages_list *pglist =
+ (struct pages_list *)vma->vm_private_data;
+
+ pages_list_put(pglist);
+ vma->vm_private_data = NULL;
}
static const struct vm_operations_struct habmem_vm_ops = {
@@ -418,6 +530,51 @@ static const struct vm_operations_struct habmem_vm_ops = {
.close = hab_map_close,
};
+static int hab_buffer_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+ struct pages_list *pglist = vma->vm_private_data;
+ pgoff_t page_offset;
+ int ret;
+
+ page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
+ PAGE_SHIFT;
+
+ if (page_offset > pglist->npages)
+ return VM_FAULT_SIGBUS;
+
+ ret = vm_insert_page(vma, (unsigned long)vmf->virtual_address,
+ pglist->pages[page_offset]);
+
+ switch (ret) {
+ case 0:
+ return VM_FAULT_NOPAGE;
+ case -ENOMEM:
+ return VM_FAULT_OOM;
+ case -EBUSY:
+ return VM_FAULT_RETRY;
+ case -EFAULT:
+ case -EINVAL:
+ return VM_FAULT_SIGBUS;
+ default:
+ WARN_ON(1);
+ return VM_FAULT_SIGBUS;
+ }
+}
+
+static void hab_buffer_open(struct vm_area_struct *vma)
+{
+}
+
+static void hab_buffer_close(struct vm_area_struct *vma)
+{
+}
+
+static const struct vm_operations_struct hab_buffer_vm_ops = {
+ .fault = hab_buffer_fault,
+ .open = hab_buffer_open,
+ .close = hab_buffer_close,
+};
+
static int hab_mem_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
{
struct pages_list *pglist = dmabuf->priv;
@@ -431,7 +588,7 @@ static int hab_mem_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
return -EINVAL;
vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
- vma->vm_ops = &habmem_vm_ops;
+ vma->vm_ops = &hab_buffer_vm_ops;
vma->vm_private_data = pglist;
vma->vm_flags |= VM_MIXEDMAP;
@@ -440,6 +597,9 @@ static int hab_mem_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
static void hab_mem_dma_buf_release(struct dma_buf *dmabuf)
{
+ struct pages_list *pglist = dmabuf->priv;
+
+ pages_list_put(pglist);
}
static void *hab_mem_dma_buf_kmap(struct dma_buf *dmabuf,
@@ -470,82 +630,50 @@ static int habmem_imp_hyp_map_fd(void *imp_ctx,
uint32_t userflags,
int32_t *pfd)
{
- 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;
- pgprot_t prot = PAGE_KERNEL;
- int32_t fd, size;
+ int32_t fd = -1;
int ret;
+ struct dma_buf *dmabuf;
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
- if (!pfn_table || !priv)
+ if (!priv)
return -EINVAL;
- size = exp->payload_count * sizeof(struct page *);
- pages = kmalloc(size, GFP_KERNEL);
- if (!pages)
- return -ENOMEM;
-
- pglist = kzalloc(sizeof(*pglist), GFP_KERNEL);
- if (!pglist) {
- kfree(pages);
- return -ENOMEM;
- }
- 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;
- }
+ pglist = pages_list_lookup(priv, exp->export_id, exp->pchan);
+ if (pglist)
+ goto buffer_ready;
- pglist->pages = pages;
- 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;
- pglist->pchan = exp->pchan;
+ pglist = pages_list_create(imp_ctx, exp, userflags);
+ if (IS_ERR(pglist))
+ return PTR_ERR(pglist);
- if (!(userflags & HABMM_IMPORT_FLAGS_CACHED))
- prot = pgprot_writecombine(prot);
+ pages_list_add(priv, pglist);
+buffer_ready:
exp_info.ops = &dma_buf_ops;
- exp_info.size = exp->payload_count << PAGE_SHIFT;
+ exp_info.size = pglist->npages << PAGE_SHIFT;
exp_info.flags = O_RDWR;
exp_info.priv = pglist;
- pglist->dmabuf = dma_buf_export(&exp_info);
- if (IS_ERR(pglist->dmabuf)) {
- ret = PTR_ERR(pglist->dmabuf);
- kfree(pages);
- kfree(pglist);
- return ret;
+ dmabuf = dma_buf_export(&exp_info);
+ if (IS_ERR(dmabuf)) {
+ pr_err("export to dmabuf failed\n");
+ ret = PTR_ERR(dmabuf);
+ goto proc_end;
}
+ pages_list_get(pglist);
- fd = dma_buf_fd(pglist->dmabuf, O_CLOEXEC);
+ fd = dma_buf_fd(dmabuf, O_CLOEXEC);
if (fd < 0) {
- dma_buf_put(pglist->dmabuf);
- kfree(pages);
- kfree(pglist);
- return -EINVAL;
+ pr_err("dma buf to fd failed\n");
+ dma_buf_put(dmabuf);
+ ret = -EINVAL;
+ goto proc_end;
}
- pglist->refcntk++;
-
- write_lock(&priv->implist_lock);
- list_add_tail(&pglist->list, &priv->imp_list);
- priv->cnt++;
- write_unlock(&priv->implist_lock);
-
+proc_end:
*pfd = fd;
-
+ pages_list_put(pglist);
return 0;
}
@@ -554,68 +682,45 @@ static int habmem_imp_hyp_map_kva(void *imp_ctx,
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;
- unsigned long pfn;
- int i, j, k = 0, size;
pgprot_t prot = PAGE_KERNEL;
- if (!pfn_table || !priv)
+ if (!priv)
return -EINVAL;
- size = exp->payload_count * sizeof(struct page *);
- pages = kmalloc(size, GFP_KERNEL);
- if (!pages)
- return -ENOMEM;
- pglist = kzalloc(sizeof(*pglist), GFP_KERNEL);
- if (!pglist) {
- kfree(pages);
- return -ENOMEM;
- }
- 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;
- }
+ pglist = pages_list_lookup(priv, exp->export_id, exp->pchan);
+ if (pglist)
+ goto buffer_ready;
- 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;
- pglist->pchan = exp->pchan;
+ pglist = pages_list_create(imp_ctx, exp, userflags);
+ if (IS_ERR(pglist))
+ return PTR_ERR(pglist);
+
+ pages_list_add(priv, pglist);
+
+buffer_ready:
+ if (pglist->kva)
+ goto pro_end;
+
+ if (pglist->userflags != userflags) {
+ pr_info("exp %d: userflags: 0x%x -> 0x%x\n",
+ exp->export_id, pglist->userflags, userflags);
+ pglist->userflags = userflags;
+ }
if (!(userflags & HABMM_IMPORT_FLAGS_CACHED))
prot = pgprot_writecombine(prot);
pglist->kva = vmap(pglist->pages, pglist->npages, VM_MAP, prot);
if (pglist->kva == NULL) {
- kfree(pages);
pr_err("%ld pages vmap failed\n", pglist->npages);
- kfree(pglist);
return -ENOMEM;
}
- pr_debug("%ld pages vmap pass, return %p\n",
- pglist->npages, pglist->kva);
-
- pglist->refcntk++;
-
- write_lock(&priv->implist_lock);
- list_add_tail(&pglist->list, &priv->imp_list);
- priv->cnt++;
- write_unlock(&priv->implist_lock);
-
+pro_end:
*pkva = pglist->kva;
-
+ pages_list_put(pglist);
return 0;
}
@@ -624,52 +729,31 @@ static int habmem_imp_hyp_map_uva(void *imp_ctx,
uint32_t userflags,
uint64_t *index)
{
- 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, size;
- if (!pfn_table || !priv)
+ if (!priv)
return -EINVAL;
- size = exp->payload_count * sizeof(struct page *);
- pages = kmalloc(size, GFP_KERNEL);
- if (!pages)
- return -ENOMEM;
- pglist = kzalloc(sizeof(*pglist), GFP_KERNEL);
- if (!pglist) {
- kfree(pages);
- return -ENOMEM;
- }
+ pglist = pages_list_lookup(priv, exp->export_id, exp->pchan);
+ if (pglist)
+ goto buffer_ready;
- 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;
- }
+ pglist = pages_list_create(imp_ctx, exp, userflags);
+ if (IS_ERR(pglist))
+ return PTR_ERR(pglist);
- 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;
- pglist->pchan = exp->pchan;
+ pages_list_add(priv, pglist);
- write_lock(&priv->implist_lock);
- list_add_tail(&pglist->list, &priv->imp_list);
- priv->cnt++;
- write_unlock(&priv->implist_lock);
+buffer_ready:
+ if (pglist->index)
+ goto proc_end;
- *index = pglist->index << PAGE_SHIFT;
+ pglist->index = page_to_phys(pglist->pages[0]) >> PAGE_SHIFT;
+proc_end:
+ *index = pglist->index << PAGE_SHIFT;
+ pages_list_put(pglist);
return 0;
}
@@ -697,37 +781,17 @@ int habmem_imp_hyp_map(void *imp_ctx, struct hab_import *param,
int habmm_imp_hyp_unmap(void *imp_ctx, struct export_desc *exp, int kernel)
{
struct importer_context *priv = imp_ctx;
- struct pages_list *pglist, *tmp;
- int found = 0;
-
- write_lock(&priv->implist_lock);
- list_for_each_entry_safe(pglist, tmp, &priv->imp_list, list) {
- if (pglist->export_id == exp->export_id &&
- pglist->pchan == exp->pchan) {
- found = 1;
- list_del(&pglist->list);
- priv->cnt--;
- break;
- }
- }
- write_unlock(&priv->implist_lock);
+ struct pages_list *pglist;
- if (!found) {
+ pglist = pages_list_lookup(priv, exp->export_id, exp->pchan);
+ if (!pglist) {
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);
+ pages_list_remove(priv, pglist);
- if (pglist->kva)
- vunmap(pglist->kva);
-
- if (pglist->dmabuf)
- dma_buf_put(pglist->dmabuf);
-
- kfree(pglist->pages);
- kfree(pglist);
+ pages_list_put(pglist);
return 0;
}
@@ -739,12 +803,14 @@ int habmem_imp_hyp_mmap(struct file *filp, struct vm_area_struct *vma)
long length = vma->vm_end - vma->vm_start;
struct pages_list *pglist;
int bfound = 0;
+ int ret = 0;
read_lock(&imp_ctx->implist_lock);
list_for_each_entry(pglist, &imp_ctx->imp_list, list) {
if ((pglist->index == vma->vm_pgoff) &&
((length <= pglist->npages * PAGE_SIZE))) {
bfound = 1;
+ pages_list_get(pglist);
break;
}
}
@@ -758,7 +824,8 @@ int habmem_imp_hyp_mmap(struct file *filp, struct vm_area_struct *vma)
if (length > pglist->npages * PAGE_SIZE) {
pr_err("Error vma length %ld not matching page list %ld\n",
length, pglist->npages * PAGE_SIZE);
- return -EINVAL;
+ ret = -EINVAL;
+ goto proc_end;
}
vma->vm_ops = &habmem_vm_ops;
@@ -769,6 +836,10 @@ int habmem_imp_hyp_mmap(struct file *filp, struct vm_area_struct *vma)
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
return 0;
+
+proc_end:
+ pages_list_put(pglist);
+ return ret;
}
int habmm_imp_hyp_map_check(void *imp_ctx, struct export_desc *exp)
@@ -777,15 +848,11 @@ int habmm_imp_hyp_map_check(void *imp_ctx, struct export_desc *exp)
struct pages_list *pglist;
int found = 0;
- read_lock(&priv->implist_lock);
- list_for_each_entry(pglist, &priv->imp_list, list) {
- if (pglist->export_id == exp->export_id &&
- pglist->pchan == exp->pchan) {
- found = 1;
- break;
- }
+ pglist = pages_list_lookup(priv, exp->export_id, exp->pchan);
+ if (pglist) {
+ found = 1;
+ pages_list_put(pglist);
}
- read_unlock(&priv->implist_lock);
return found;
}
diff --git a/drivers/soc/qcom/hab/hab_mimex.c b/drivers/soc/qcom/hab/hab_mimex.c
index d5786170f0f3..00c6c475fa92 100644
--- a/drivers/soc/qcom/hab/hab_mimex.c
+++ b/drivers/soc/qcom/hab/hab_mimex.c
@@ -124,8 +124,11 @@ void habmem_remove_export(struct export_desc *exp)
struct uhab_context *ctx;
if (!exp || !exp->ctx || !exp->pchan) {
- pr_err("failed to find valid info in exp %pK ctx %pK pchan %pK\n",
+ if (exp)
+ pr_err("invalid info in exp %pK ctx %pK pchan %pK\n",
exp, exp->ctx, exp->pchan);
+ else
+ pr_err("invalid exp\n");
return;
}
diff --git a/drivers/soc/qcom/hab/hab_msg.c b/drivers/soc/qcom/hab/hab_msg.c
index 3765623d3190..61e658954312 100644
--- a/drivers/soc/qcom/hab/hab_msg.c
+++ b/drivers/soc/qcom/hab/hab_msg.c
@@ -76,8 +76,9 @@ hab_msg_dequeue(struct virtual_channel *vchan, struct hab_message **msg,
ret = 0;
*rsize = message->sizebytes;
} else {
- pr_err("rcv buffer too small %d < %zd\n",
- *rsize, message->sizebytes);
+ pr_err("vcid %x rcv buf too small %d < %zd\n",
+ vchan->id, *rsize,
+ message->sizebytes);
*rsize = message->sizebytes;
message = NULL;
ret = -EOVERFLOW; /* come back again */
@@ -281,7 +282,13 @@ int hab_msg_recv(struct physical_channel *pchan,
break;
}
- exp_desc->domid_local = pchan->dom_id;
+ if (pchan->vmid_local != exp_desc->domid_remote ||
+ pchan->vmid_remote != exp_desc->domid_local)
+ pr_err("corrupted vmid %d != %d %d != %d\n",
+ pchan->vmid_local, exp_desc->domid_remote,
+ pchan->vmid_remote, exp_desc->domid_local);
+ exp_desc->domid_remote = pchan->vmid_remote;
+ exp_desc->domid_local = pchan->vmid_local;
exp_desc->pchan = pchan;
hab_export_enqueue(vchan, exp_desc);
diff --git a/drivers/soc/qcom/hab/hab_open.c b/drivers/soc/qcom/hab/hab_open.c
index f740a43c1973..f09a1df8aa57 100644
--- a/drivers/soc/qcom/hab/hab_open.c
+++ b/drivers/soc/qcom/hab/hab_open.c
@@ -152,10 +152,13 @@ int hab_open_listen(struct uhab_context *ctx,
ret = wait_event_interruptible_timeout(dev->openq,
hab_open_request_find(ctx, dev, listen, recv_request),
ms_timeout);
- if (!ret || (-ERESTARTSYS == ret)) {
+ if (!ret) {
+ pr_debug("%s timeout in open listen\n", dev->name);
+ ret = -EAGAIN; /* condition not met */
+ } else if (-ERESTARTSYS == ret) {
pr_warn("something failed in open listen ret %d\n",
ret);
- ret = -EAGAIN; /* condition not met */
+ ret = -EINTR; /* condition not met */
} else if (ret > 0)
ret = 0; /* condition met */
} else { /* fe case */
diff --git a/drivers/soc/qcom/hab/hab_vchan.c b/drivers/soc/qcom/hab/hab_vchan.c
index e42b27f5048d..8d818b8fafb1 100644
--- a/drivers/soc/qcom/hab/hab_vchan.c
+++ b/drivers/soc/qcom/hab/hab_vchan.c
@@ -87,7 +87,6 @@ hab_vchan_free(struct kref *ref)
/* the release vchan from ctx was done earlier in vchan close() */
hab_ctx_put(ctx); /* now ctx is not needed from this vchan's view */
- vchan->ctx = NULL;
/* release vchan from pchan. no more msg for this vchan */
write_lock_bh(&pchan->vchans_lock);
@@ -144,6 +143,13 @@ hab_vchan_get(struct physical_channel *pchan, struct hab_header *header)
get_refcnt(vchan->refcount),
payload_type, sizebytes);
vchan = NULL;
+ } else if (vchan->otherend_closed || vchan->closed) {
+ pr_err("closed already remote %d local %d vcid %x remote %x session %d refcnt %d header %x session %d type %d sz %zd\n",
+ vchan->otherend_closed, vchan->closed,
+ vchan->id, vchan->otherend_id,
+ vchan->session_id, get_refcnt(vchan->refcount),
+ vchan_id, session_id, payload_type, sizebytes);
+ vchan = NULL;
} else if (!kref_get_unless_zero(&vchan->refcount)) {
/*
* this happens when refcnt is already zero
@@ -154,13 +160,6 @@ hab_vchan_get(struct physical_channel *pchan, struct hab_header *header)
vchan->session_id, get_refcnt(vchan->refcount),
vchan_id, session_id, payload_type, sizebytes);
vchan = NULL;
- } else if (vchan->otherend_closed || vchan->closed) {
- pr_err("closed already remote %d local %d vcid %x remote %x session %d refcnt %d header %x session %d type %d sz %zd\n",
- vchan->otherend_closed, vchan->closed,
- vchan->id, vchan->otherend_id,
- vchan->session_id, get_refcnt(vchan->refcount),
- vchan_id, session_id, payload_type, sizebytes);
- vchan = NULL;
}
}
spin_unlock_bh(&pchan->vid_lock);
@@ -173,7 +172,10 @@ void hab_vchan_stop(struct virtual_channel *vchan)
if (vchan) {
vchan->otherend_closed = 1;
wake_up(&vchan->rx_queue);
- wake_up_interruptible(&vchan->ctx->exp_wq);
+ if (vchan->ctx)
+ wake_up_interruptible(&vchan->ctx->exp_wq);
+ else
+ pr_err("NULL ctx for vchan %x\n", vchan->id);
}
}
@@ -200,6 +202,18 @@ static int hab_vchans_per_pchan_empty(struct physical_channel *pchan)
read_lock(&pchan->vchans_lock);
empty = list_empty(&pchan->vchannels);
+ if (!empty) {
+ struct virtual_channel *vchan;
+
+ list_for_each_entry(vchan, &pchan->vchannels, pnode) {
+ pr_err("vchan %pK id %x remote id %x session %d ref %d closed %d remote close %d\n",
+ vchan, vchan->id, vchan->otherend_id,
+ vchan->session_id,
+ get_refcnt(vchan->refcount), vchan->closed,
+ vchan->otherend_closed);
+ }
+
+ }
read_unlock(&pchan->vchans_lock);
return empty;
@@ -220,6 +234,8 @@ static int hab_vchans_empty(int vmid)
if (!hab_vchans_per_pchan_empty(pchan)) {
empty = 0;
spin_unlock_bh(&hab_dev->pchan_lock);
+ pr_info("vmid %d %s's vchans are not closed\n",
+ vmid, pchan->name);
break;
}
}
@@ -239,7 +255,7 @@ void hab_vchans_empty_wait(int vmid)
pr_info("waiting for GVM%d's sockets closure\n", vmid);
while (!hab_vchans_empty(vmid))
- schedule();
+ usleep_range(10000, 12000);
pr_info("all of GVM%d's sockets are closed\n", vmid);
}
diff --git a/drivers/soc/qcom/qdsp6v2/audio-anc-dev-mgr.c b/drivers/soc/qcom/qdsp6v2/audio-anc-dev-mgr.c
index 75b114e6905c..95562d2cbfad 100644
--- a/drivers/soc/qcom/qdsp6v2/audio-anc-dev-mgr.c
+++ b/drivers/soc/qcom/qdsp6v2/audio-anc-dev-mgr.c
@@ -53,8 +53,6 @@ struct anc_tdm_group_set_info {
struct anc_dev_drv_info {
uint32_t state;
- uint32_t rpm;
- uint32_t bypass_mode;
uint32_t algo_module_id;
};
@@ -311,52 +309,68 @@ static int anc_dev_port_stop(int32_t which_port)
int msm_anc_dev_set_info(void *info_p, int32_t anc_cmd)
{
- int rc = 0;
+ int rc = -EINVAL;
switch (anc_cmd) {
- case ANC_CMD_RPM: {
- struct audio_anc_rpm_info *rpm_info_p =
- (struct audio_anc_rpm_info *)info_p;
+ case ANC_CMD_ALGO_MODULE: {
+ struct audio_anc_algo_module_info *module_info_p =
+ (struct audio_anc_algo_module_info *)info_p;
+
+ rc = 0;
if (this_anc_dev_info.state)
- rc = anc_if_set_rpm(
+ rc = anc_if_set_algo_module_id(
anc_port_cfg[ANC_DEV_PORT_ANC_SPKR].port_id,
- rpm_info_p->rpm);
+ module_info_p->module_id);
else
- this_anc_dev_info.rpm = 0;
+ this_anc_dev_info.algo_module_id =
+ module_info_p->module_id;
break;
}
- case ANC_CMD_BYPASS_MODE: {
- struct audio_anc_bypass_mode *bypass_mode_p =
- (struct audio_anc_bypass_mode *)info_p;
-
+ case ANC_CMD_ALGO_CALIBRATION: {
+ rc = -EINVAL;
if (this_anc_dev_info.state)
- rc = anc_if_set_bypass_mode(
+ rc = anc_if_set_algo_module_cali_data(
anc_port_cfg[ANC_DEV_PORT_ANC_SPKR].port_id,
- bypass_mode_p->mode);
+ info_p);
else
- this_anc_dev_info.bypass_mode = bypass_mode_p->mode;
+ pr_err("%s: ANC is not running yet\n",
+ __func__);
+ break;
+ }
+ default:
+ pr_err("%s: ANC cmd wrong\n",
+ __func__);
break;
}
- case ANC_CMD_ALGO_MODULE: {
- struct audio_anc_algo_module_info *module_info_p =
- (struct audio_anc_algo_module_info *)info_p;
+ return rc;
+}
+
+int msm_anc_dev_get_info(void *info_p, int32_t anc_cmd)
+{
+ int rc = -EINVAL;
+
+ switch (anc_cmd) {
+ case ANC_CMD_ALGO_CALIBRATION: {
if (this_anc_dev_info.state)
- rc = anc_if_set_algo_module_id(
+ rc = anc_if_get_algo_module_cali_data(
anc_port_cfg[ANC_DEV_PORT_ANC_SPKR].port_id,
- module_info_p->module_id);
+ info_p);
else
- this_anc_dev_info.algo_module_id =
- module_info_p->module_id;
+ pr_err("%s: ANC is not running yet\n",
+ __func__);
break;
}
+ default:
+ pr_err("%s: ANC cmd wrong\n",
+ __func__);
+ break;
}
return rc;
}
-
int msm_anc_dev_start(void)
{
int rc = 0;
@@ -514,11 +528,6 @@ int msm_anc_dev_start(void)
anc_port_cfg[ANC_DEV_PORT_ANC_SPKR].port_id,
this_anc_dev_info.algo_module_id);
- if (this_anc_dev_info.bypass_mode != 0)
- rc = anc_if_set_bypass_mode(
- anc_port_cfg[ANC_DEV_PORT_ANC_SPKR].port_id,
- this_anc_dev_info.bypass_mode);
-
group_id = get_group_id_from_port_id(
anc_port_cfg[ANC_DEV_PORT_ANC_SPKR].port_id);
@@ -612,8 +621,6 @@ int msm_anc_dev_stop(void)
this_anc_dev_info.state = 0;
this_anc_dev_info.algo_module_id = 0;
- this_anc_dev_info.rpm = 0;
- this_anc_dev_info.bypass_mode = 0;
pr_debug("%s: ANC devices stop successfully!\n", __func__);
diff --git a/drivers/soc/qcom/qdsp6v2/audio_anc.c b/drivers/soc/qcom/qdsp6v2/audio_anc.c
index 65c585886453..50cc255043df 100644
--- a/drivers/soc/qcom/qdsp6v2/audio_anc.c
+++ b/drivers/soc/qcom/qdsp6v2/audio_anc.c
@@ -44,17 +44,11 @@ static size_t get_user_anc_cmd_size(int32_t anc_cmd)
case ANC_CMD_STOP:
size = 0;
break;
- case ANC_CMD_RPM:
- size = sizeof(struct audio_anc_rpm_info);
- break;
- case ANC_CMD_BYPASS_MODE:
- size = sizeof(struct audio_anc_bypass_mode);
- break;
case ANC_CMD_ALGO_MODULE:
size = sizeof(struct audio_anc_algo_module_info);
break;
case ANC_CMD_ALGO_CALIBRATION:
- size = sizeof(struct audio_anc_algo_calibration_info);
+ size = sizeof(struct audio_anc_algo_calibration_header);
break;
default:
pr_err("%s:Invalid anc cmd %d!",
@@ -77,8 +71,6 @@ static int call_set_anc(int32_t anc_cmd,
case ANC_CMD_STOP:
ret = msm_anc_dev_stop();
break;
- case ANC_CMD_RPM:
- case ANC_CMD_BYPASS_MODE:
case ANC_CMD_ALGO_MODULE:
case ANC_CMD_ALGO_CALIBRATION:
ret = msm_anc_dev_set_info(data, anc_cmd);
@@ -98,7 +90,8 @@ static int call_get_anc(int32_t anc_cmd,
int ret = 0;
switch (anc_cmd) {
- case ANC_CMD_RPM:
+ case ANC_CMD_ALGO_CALIBRATION:
+ ret = msm_anc_dev_get_info(data, anc_cmd);
break;
default:
break;
@@ -146,9 +139,9 @@ static long audio_anc_shared_ioctl(struct file *file, unsigned int cmd,
pr_err("%s: Could not copy size value from user\n", __func__);
ret = -EFAULT;
goto done;
- } else if (size < sizeof(struct audio_anc_packet)) {
+ } else if (size < sizeof(struct audio_anc_header)) {
pr_err("%s: Invalid size sent to driver: %d, min size is %zd\n",
- __func__, size, sizeof(struct audio_anc_packet));
+ __func__, size, sizeof(struct audio_anc_header));
ret = -EINVAL;
goto done;
}
diff --git a/drivers/soc/qcom/qdsp6v2/sdsp-anc.c b/drivers/soc/qcom/qdsp6v2/sdsp-anc.c
index 9294485f7ff2..4e75bc89aa8f 100644
--- a/drivers/soc/qcom/qdsp6v2/sdsp-anc.c
+++ b/drivers/soc/qcom/qdsp6v2/sdsp-anc.c
@@ -38,7 +38,7 @@ struct anc_if_ctl {
atomic_t status;
wait_queue_head_t wait[AFE_MAX_PORTS];
struct task_struct *task;
- struct anc_get_rpm_resp rpm_calib_data;
+ struct anc_get_algo_module_cali_data_resp cali_data_resp;
uint32_t mmap_handle;
struct mutex afe_cmd_lock;
};
@@ -48,33 +48,23 @@ static struct anc_if_ctl this_anc_if;
static int32_t anc_get_param_callback(uint32_t *payload,
uint32_t payload_size)
{
- u32 param_id;
- struct anc_get_rpm_resp *resp =
- (struct anc_get_rpm_resp *) payload;
-
- if (!(&(resp->pdata))) {
- pr_err("%s: Error: resp pdata is NULL\n", __func__);
+ if ((payload_size < (sizeof(uint32_t) +
+ sizeof(this_anc_if.cali_data_resp.pdata))) ||
+ (payload_size > sizeof(this_anc_if.cali_data_resp))) {
+ pr_err("%s: Error: received size %d, calib_data size %zu\n",
+ __func__, payload_size,
+ sizeof(this_anc_if.cali_data_resp));
return -EINVAL;
}
- param_id = resp->pdata.param_id;
- if (param_id == AUD_MSVC_PARAM_ID_PORT_ANC_ALGO_RPM) {
- if (payload_size < sizeof(this_anc_if.rpm_calib_data)) {
- pr_err("%s: Error: received size %d, calib_data size %zu\n",
- __func__, payload_size,
- sizeof(this_anc_if.rpm_calib_data));
- return -EINVAL;
- }
-
- memcpy(&this_anc_if.rpm_calib_data, payload,
- sizeof(this_anc_if.rpm_calib_data));
- if (!this_anc_if.rpm_calib_data.status) {
- atomic_set(&this_anc_if.state, 0);
- } else {
- pr_debug("%s: calib resp status: %d", __func__,
- this_anc_if.rpm_calib_data.status);
- atomic_set(&this_anc_if.state, -1);
- }
+ memcpy(&this_anc_if.cali_data_resp, payload,
+ payload_size);
+ if (!this_anc_if.cali_data_resp.status) {
+ atomic_set(&this_anc_if.state, 0);
+ } else {
+ pr_debug("%s: calib resp status: %d", __func__,
+ this_anc_if.cali_data_resp.status);
+ atomic_set(&this_anc_if.state, -1);
}
return 0;
@@ -465,7 +455,7 @@ int anc_if_tdm_port_stop(u16 port_id)
return anc_if_send_cmd_port_stop(port_id);
}
-int anc_if_set_rpm(u16 port_id, u32 rpm)
+int anc_if_set_algo_module_id(u16 port_id, u32 module_id)
{
int ret = 0;
int index;
@@ -479,7 +469,7 @@ int anc_if_set_rpm(u16 port_id, u32 rpm)
index = q6audio_get_port_index(port_id);
{
- struct anc_set_rpm_command config;
+ struct anc_set_algo_module_id_command config;
memset(&config, 0, sizeof(config));
config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -496,16 +486,16 @@ int anc_if_set_rpm(u16 port_id, u32 rpm)
config.param.payload_address_lsw = 0x00;
config.param.payload_address_msw = 0x00;
config.param.mem_map_handle = 0x00;
- config.pdata.module_id = AUD_MSVC_MODULE_AUDIO_DEV_ANC_ALGO;
- config.pdata.param_id = AUD_MSVC_PARAM_ID_PORT_ANC_ALGO_RPM;
- config.pdata.param_size = sizeof(config.set_rpm);
- config.set_rpm.minor_version =
- AUD_MSVC_API_VERSION_DEV_ANC_ALGO_RPM;
- config.set_rpm.rpm = rpm;
+ config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
+ config.pdata.param_id =
+ AUD_MSVC_PARAM_ID_PORT_ANC_ALGO_MODULE_ID;
+ config.pdata.param_size = sizeof(config.set_algo_module_id);
+ config.set_algo_module_id.minor_version = 1;
+ config.set_algo_module_id.module_id = module_id;
ret = anc_if_apr_send_pkt(&config, &this_anc_if.wait[index]);
if (ret) {
- pr_err("%s: share resource for port 0x%x failed ret = %d\n",
+ pr_err("%s: anc algo module ID for port 0x%x failed ret = %d\n",
__func__, port_id, ret);
}
}
@@ -513,10 +503,10 @@ int anc_if_set_rpm(u16 port_id, u32 rpm)
return ret;
}
-int anc_if_set_bypass_mode(u16 port_id, u32 bypass_mode)
+int anc_if_set_anc_mic_spkr_layout(u16 port_id,
+struct aud_msvc_param_id_dev_anc_mic_spkr_layout_info *set_mic_spkr_layout_p)
{
int ret = 0;
-
int index;
ret = anc_sdsp_interface_prepare();
@@ -528,7 +518,7 @@ int anc_if_set_bypass_mode(u16 port_id, u32 bypass_mode)
index = q6audio_get_port_index(port_id);
{
- struct anc_set_bypass_mode_command config;
+ struct anc_set_mic_spkr_layout_info_command config;
memset(&config, 0, sizeof(config));
config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -545,17 +535,16 @@ int anc_if_set_bypass_mode(u16 port_id, u32 bypass_mode)
config.param.payload_address_lsw = 0x00;
config.param.payload_address_msw = 0x00;
config.param.mem_map_handle = 0x00;
- config.pdata.module_id = AUD_MSVC_MODULE_AUDIO_DEV_ANC_ALGO;
+ config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
config.pdata.param_id =
- AUD_MSVC_PARAM_ID_PORT_ANC_ALGO_BYPASS_MODE;
- config.pdata.param_size = sizeof(config.set_bypass_mode);
- config.set_bypass_mode.minor_version =
- AUD_MSVC_API_VERSION_DEV_ANC_ALGO_BYPASS_MODE;
- config.set_bypass_mode.bypass_mode = bypass_mode;
+ AUD_MSVC_PARAM_ID_PORT_ANC_MIC_SPKR_LAYOUT_INFO;
+ config.pdata.param_size = sizeof(config.set_mic_spkr_layout);
+ memcpy(&config.set_mic_spkr_layout, set_mic_spkr_layout_p,
+ sizeof(config.set_mic_spkr_layout));
ret = anc_if_apr_send_pkt(&config, &this_anc_if.wait[index]);
if (ret) {
- pr_err("%s: share resource for port 0x%x failed ret = %d\n",
+ pr_err("%s: anc algo module ID for port 0x%x failed ret = %d\n",
__func__, port_id, ret);
}
}
@@ -563,10 +552,10 @@ int anc_if_set_bypass_mode(u16 port_id, u32 bypass_mode)
return ret;
}
-int anc_if_set_algo_module_id(u16 port_id, u32 module_id)
+
+int anc_if_set_algo_module_cali_data(u16 port_id, void *data_p)
{
int ret = 0;
-
int index;
ret = anc_sdsp_interface_prepare();
@@ -578,45 +567,67 @@ int anc_if_set_algo_module_id(u16 port_id, u32 module_id)
index = q6audio_get_port_index(port_id);
{
- struct anc_set_algo_module_id_command config;
+ struct anc_set_algo_module_cali_data_command *cali_data_cfg_p;
+ void *config_p = NULL;
+ int cmd_size = 0;
+ void *out_payload_p = NULL;
+ uint32_t *in_payload_p = (uint32_t *)data_p;
+
+ uint32_t module_id = *in_payload_p;
+ uint32_t param_id = *(in_payload_p + 1);
+ uint32_t payload_size = *(in_payload_p + 2);
+
+ cmd_size = sizeof(struct anc_set_algo_module_cali_data_command)
+ + payload_size;
+ config_p = kzalloc(cmd_size, GFP_KERNEL);
+ if (!config_p) {
+ ret = -ENOMEM;
+ return ret;
+ }
- memset(&config, 0, sizeof(config));
- config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ memset(config_p, 0, cmd_size);
+ out_payload_p = config_p
+ + sizeof(struct anc_set_algo_module_cali_data_command);
+
+ cali_data_cfg_p =
+ (struct anc_set_algo_module_cali_data_command *)config_p;
+
+ cali_data_cfg_p->hdr.hdr_field =
+ APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- config.hdr.pkt_size = sizeof(config);
- config.hdr.src_port = 0;
- config.hdr.dest_port = 0;
- config.hdr.token = index;
- config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
- config.param.port_id = q6audio_get_port_id(port_id);
- config.param.payload_size = sizeof(config) -
+ cali_data_cfg_p->hdr.pkt_size = cmd_size;
+ cali_data_cfg_p->hdr.src_port = 0;
+ cali_data_cfg_p->hdr.dest_port = 0;
+ cali_data_cfg_p->hdr.token = index;
+ cali_data_cfg_p->hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
+ cali_data_cfg_p->param.port_id = q6audio_get_port_id(port_id);
+ cali_data_cfg_p->param.payload_size = cmd_size -
sizeof(struct apr_hdr) -
- sizeof(config.param);
- config.param.payload_address_lsw = 0x00;
- config.param.payload_address_msw = 0x00;
- config.param.mem_map_handle = 0x00;
- config.pdata.module_id = AUD_MSVC_MODULE_AUDIO_DEV_ANC_ALGO;
- config.pdata.param_id =
- AUD_MSVC_PARAM_ID_PORT_ANC_ALGO_MODULE_ID;
- config.pdata.param_size = sizeof(config.set_algo_module_id);
- config.set_algo_module_id.minor_version = 1;
- config.set_algo_module_id.module_id = module_id;
+ sizeof(struct aud_msvc_port_cmd_set_param_v2);
+ cali_data_cfg_p->param.payload_address_lsw = 0x00;
+ cali_data_cfg_p->param.payload_address_msw = 0x00;
+ cali_data_cfg_p->param.mem_map_handle = 0x00;
+ cali_data_cfg_p->pdata.module_id = module_id;
+ cali_data_cfg_p->pdata.param_id = param_id;
+ cali_data_cfg_p->pdata.param_size = payload_size;
+
+ memcpy(out_payload_p, (in_payload_p + 3), payload_size);
+
+ ret = anc_if_apr_send_pkt(cali_data_cfg_p,
+ &this_anc_if.wait[index]);
+ if (ret)
+ pr_err("%s: anc algo module calibration data for port 0x%x failed ret = %d\n",
+ __func__, port_id, ret);
- ret = anc_if_apr_send_pkt(&config, &this_anc_if.wait[index]);
- if (ret) {
- pr_err("%s: anc algo module ID for port 0x%x failed ret = %d\n",
- __func__, port_id, ret);
- }
+ kfree(config_p);
}
return ret;
}
-int anc_if_set_anc_mic_spkr_layout(u16 port_id,
-struct aud_msvc_param_id_dev_anc_mic_spkr_layout_info *set_mic_spkr_layout_p)
+int anc_if_get_algo_module_cali_data(u16 port_id, void *data_p)
{
int ret = 0;
-
int index;
ret = anc_sdsp_interface_prepare();
@@ -628,35 +639,68 @@ struct aud_msvc_param_id_dev_anc_mic_spkr_layout_info *set_mic_spkr_layout_p)
index = q6audio_get_port_index(port_id);
{
- struct anc_set_mic_spkr_layout_info_command config;
+ struct anc_get_algo_module_cali_data_command *cali_data_cfg_p;
+ void *config_p = NULL;
+ int cmd_size = 0;
+ void *out_payload_p = NULL;
+ uint32_t *in_payload_p = (uint32_t *)data_p;
+
+ uint32_t module_id = *in_payload_p;
+ uint32_t param_id = *(in_payload_p + 1);
+ uint32_t payload_size = *(in_payload_p + 2);
+
+ cmd_size = sizeof(struct anc_get_algo_module_cali_data_command)
+ + payload_size;
+ config_p = kzalloc(cmd_size, GFP_KERNEL);
+ if (!config_p) {
+ ret = -ENOMEM;
+ return ret;
+ }
- memset(&config, 0, sizeof(config));
- config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ memset(config_p, 0, cmd_size);
+ out_payload_p = config_p +
+ sizeof(struct anc_set_algo_module_cali_data_command);
+
+ cali_data_cfg_p =
+ (struct anc_get_algo_module_cali_data_command *)config_p;
+
+ cali_data_cfg_p->hdr.hdr_field =
+ APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- config.hdr.pkt_size = sizeof(config);
- config.hdr.src_port = 0;
- config.hdr.dest_port = 0;
- config.hdr.token = index;
- config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
- config.param.port_id = q6audio_get_port_id(port_id);
- config.param.payload_size = sizeof(config) -
+ cali_data_cfg_p->hdr.pkt_size = cmd_size;
+ cali_data_cfg_p->hdr.src_port = 0;
+ cali_data_cfg_p->hdr.dest_port = 0;
+ cali_data_cfg_p->hdr.token = index;
+ cali_data_cfg_p->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
+ cali_data_cfg_p->param.port_id = q6audio_get_port_id(port_id);
+ cali_data_cfg_p->param.payload_size = cmd_size -
sizeof(struct apr_hdr) -
- sizeof(config.param);
- config.param.payload_address_lsw = 0x00;
- config.param.payload_address_msw = 0x00;
- config.param.mem_map_handle = 0x00;
- config.pdata.module_id = AUD_MSVC_MODULE_AUDIO_DEV_ANC_ALGO;
- config.pdata.param_id =
- AUD_MSVC_PARAM_ID_PORT_ANC_MIC_SPKR_LAYOUT_INFO;
- config.pdata.param_size = sizeof(config.set_mic_spkr_layout);
-
- memcpy(&config.set_mic_spkr_layout, set_mic_spkr_layout_p,
- sizeof(config.set_mic_spkr_layout));
- ret = anc_if_apr_send_pkt(&config, &this_anc_if.wait[index]);
- if (ret) {
- pr_err("%s: anc algo module ID for port 0x%x failed ret = %d\n",
+ sizeof(struct aud_msvc_port_cmd_get_param_v2);
+ cali_data_cfg_p->param.payload_address_lsw = 0x00;
+ cali_data_cfg_p->param.payload_address_msw = 0x00;
+ cali_data_cfg_p->param.mem_map_handle = 0x00;
+ cali_data_cfg_p->param.module_id = module_id;
+ cali_data_cfg_p->param.param_id = param_id;
+ cali_data_cfg_p->pdata.param_size = 0;
+ cali_data_cfg_p->pdata.module_id = 0;
+ cali_data_cfg_p->pdata.param_id = 0;
+
+ ret = anc_if_apr_send_pkt(cali_data_cfg_p,
+ &this_anc_if.wait[index]);
+ if (ret)
+ pr_err("%s: anc algo module calibration data for port 0x%x failed ret = %d\n",
__func__, port_id, ret);
- }
+
+ memcpy((in_payload_p + 3),
+ &this_anc_if.cali_data_resp.payload[0], payload_size);
+
+ *in_payload_p = this_anc_if.cali_data_resp.pdata.module_id;
+ *(in_payload_p + 1) =
+ this_anc_if.cali_data_resp.pdata.param_id;
+ *(in_payload_p + 2) =
+ this_anc_if.cali_data_resp.pdata.param_size;
+
+ kfree(config_p);
}
return ret;
@@ -700,7 +744,6 @@ int anc_if_cmd_memory_map(int port_id, phys_addr_t dma_addr_p,
mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
if (!mmap_region_cmd) {
ret = -ENOMEM;
- pr_err("%s: allocate mmap_region_cmd failed\n", __func__);
return ret;
}
diff --git a/drivers/soc/qcom/subsystem_notif_virt.c b/drivers/soc/qcom/subsystem_notif_virt.c
index f8ce53cfa9f7..5c9acf7e4563 100644
--- a/drivers/soc/qcom/subsystem_notif_virt.c
+++ b/drivers/soc/qcom/subsystem_notif_virt.c
@@ -43,7 +43,7 @@ struct subsystem_descriptor {
enum subsystem_type type;
struct notifier_block nb;
void *handle;
- unsigned int ssr_irq;
+ int ssr_irq;
struct list_head subsystem_list;
struct work_struct work;
};
@@ -91,7 +91,7 @@ static int subsys_notif_virt_probe(struct platform_device *pdev)
struct device_node *child = NULL;
const char *ss_type;
struct resource *res;
- struct subsystem_descriptor *subsystem;
+ struct subsystem_descriptor *subsystem = NULL;
int ret = 0;
if (!pdev) {
@@ -193,7 +193,8 @@ static int subsys_notif_virt_probe(struct platform_device *pdev)
}
}
- INIT_WORK(&subsystem->work, subsystem_notif_wq_func);
+ if (subsystem)
+ INIT_WORK(&subsystem->work, subsystem_notif_wq_func);
return 0;
err:
destroy_workqueue(ssr_wq);
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index 4670e2f4c2de..278df845f066 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -279,13 +279,24 @@ config USB_QTI_KS_BRIDGE
To compile this driver as a module, choose M here: the module
will be called ks_bridge. If unsure, choose N.
+config USB_QCOM_IPC_BRIDGE
+ tristate "USB QTI IPC bridge driver"
+ depends on USB
+ depends on USB_QCOM_DIAG_BRIDGE
+ help
+ Say Y here if you have a QTI modem device connected via USB that
+ will be bridged in kernel space. This driver works as a transport
+ layer for IPC router module that enables communication between
+ APPS processor and MODEM processor.
+
config USB_QCOM_DIAG_BRIDGE
tristate "USB QTI diagnostic bridge driver"
depends on USB
+ select USB_QCOM_IPC_BRIDGE
help
Say Y here if you have a QTI modem device connected via USB that
will be bridged in kernel space. This driver communicates with the
- diagnostic and QMI interfaces and allows for bridging with the diag
- forwarding driver for diag interface and IPC router for QMI interface.
+ diagnostic interface and allows for bridging with the diag forwarding
+ driver.
To compile this driver as a module, choose M here: the
module will be called diag_bridge. If unsure, choose N.
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index 0d41f41371dd..69b9149cd750 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -2043,10 +2043,9 @@ static void __mdss_dsi_calc_dfps_delay(struct mdss_panel_data *pdata)
}
static int __mdss_dsi_dfps_calc_clks(struct mdss_panel_data *pdata,
- int new_fps)
+ u64 new_clk_rate)
{
int rc = 0;
- u64 clk_rate;
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
struct mdss_panel_info *pinfo;
u32 phy_rev;
@@ -2066,14 +2065,9 @@ static int __mdss_dsi_dfps_calc_clks(struct mdss_panel_data *pdata,
pinfo = &pdata->panel_info;
phy_rev = ctrl_pdata->shared_data->phy_rev;
- rc = mdss_dsi_clk_div_config
- (&ctrl_pdata->panel_data.panel_info, new_fps);
- if (rc) {
- pr_err("%s: unable to initialize the clk dividers\n",
- __func__);
- return rc;
- }
-
+ pinfo->clk_rate = new_clk_rate;
+ pinfo->mipi.dsi_pclk_rate = mdss_dsi_get_pclk_rate(pinfo,
+ new_clk_rate);
__mdss_dsi_dyn_refresh_config(ctrl_pdata);
if (phy_rev == DSI_PHY_REV_20)
@@ -2086,9 +2080,8 @@ static int __mdss_dsi_dfps_calc_clks(struct mdss_panel_data *pdata,
ctrl_pdata->byte_clk_rate_bkp = ctrl_pdata->byte_clk_rate;
ctrl_pdata->pclk_rate = pinfo->mipi.dsi_pclk_rate;
- clk_rate = pinfo->clk_rate;
- do_div(clk_rate, 8U);
- ctrl_pdata->byte_clk_rate = (u32) clk_rate;
+ do_div(new_clk_rate, 8U);
+ ctrl_pdata->byte_clk_rate = (u32) new_clk_rate;
pr_debug("byte_rate=%i\n", ctrl_pdata->byte_clk_rate);
pr_debug("pclk_rate=%i\n", ctrl_pdata->pclk_rate);
@@ -2096,8 +2089,7 @@ static int __mdss_dsi_dfps_calc_clks(struct mdss_panel_data *pdata,
return rc;
}
-static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata,
- int new_fps)
+static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata)
{
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
struct mdss_dsi_ctrl_pdata *sctrl_pdata = NULL;
@@ -2248,12 +2240,6 @@ static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata,
clk_disable_unprepare(ctrl_pdata->pll_byte_clk);
clk_disable_unprepare(ctrl_pdata->pll_pixel_clk);
- /* update new fps that at this point is already updated in hw */
- pinfo->current_fps = new_fps;
- if (sctrl_pdata) {
- spinfo->current_fps = new_fps;
- }
-
return rc;
dfps_timeout:
@@ -2330,13 +2316,65 @@ static void mdss_dsi_avr_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata,
MDSS_XLOG(ctrl_pdata->ndx, enabled, data);
}
-static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps)
+static int __mdss_dsi_dynamic_clock_switch(struct mdss_panel_data *pdata,
+ u64 new_clk_rate)
{
int rc = 0;
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
struct mdss_panel_info *pinfo;
u32 phy_rev;
- u32 frame_rate_bkp;
+ u64 clk_rate_bkp;
+
+ pr_debug("%s+:\n", __func__);
+
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
+
+ phy_rev = ctrl_pdata->shared_data->phy_rev;
+ pinfo = &pdata->panel_info;
+
+ /* get the fps configured in HW */
+ clk_rate_bkp = pinfo->clk_rate;
+
+ __mdss_dsi_mask_dfps_errors(ctrl_pdata, true);
+
+ if (phy_rev == DSI_PHY_REV_20) {
+ rc = mdss_dsi_phy_calc_timing_param(pinfo, phy_rev,
+ new_clk_rate);
+ if (rc) {
+ pr_err("PHY calculations failed-%lld\n", new_clk_rate);
+ goto end_update;
+ }
+ }
+
+ rc = __mdss_dsi_dfps_calc_clks(pdata, new_clk_rate);
+ if (rc) {
+ pr_err("error calculating clocks for %lld\n", new_clk_rate);
+ goto error_clks;
+ }
+
+ rc = __mdss_dsi_dfps_update_clks(pdata);
+ if (rc) {
+ pr_err("Dynamic refresh failed-%lld\n", new_clk_rate);
+ goto error_dfps;
+ }
+ return rc;
+error_dfps:
+ if (__mdss_dsi_dfps_calc_clks(pdata, clk_rate_bkp))
+ pr_err("error reverting clock calculations for %lld\n",
+ clk_rate_bkp);
+error_clks:
+ if (mdss_dsi_phy_calc_timing_param(pinfo, phy_rev, clk_rate_bkp))
+ pr_err("Unable to revert phy timing-%lld\n", clk_rate_bkp);
+end_update:
+ return rc;
+}
+
+static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps)
+{
+ int rc = 0;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+ struct mdss_panel_info *pinfo;
pr_debug("%s+:\n", __func__);
@@ -2353,12 +2391,8 @@ static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps)
return -EINVAL;
}
- phy_rev = ctrl_pdata->shared_data->phy_rev;
pinfo = &pdata->panel_info;
- /* get the fps configured in HW */
- frame_rate_bkp = pinfo->current_fps;
-
if (new_fps == pinfo->current_fps) {
/*
* This is unlikely as mdss driver checks for previously
@@ -2374,39 +2408,45 @@ static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps)
__mdss_dsi_update_video_mode_total(pdata, new_fps);
} else if (pinfo->dfps_update == DFPS_IMMEDIATE_CLK_UPDATE_MODE) {
/* Clock update method */
+ u64 new_clk_rate = mdss_dsi_calc_bitclk
+ (&ctrl_pdata->panel_data.panel_info, new_fps);
+ if (!new_clk_rate) {
+ pr_err("%s: unable to get the new bit clock rate\n",
+ __func__);
+ rc = -EINVAL;
+ goto end_update;
+ }
- __mdss_dsi_mask_dfps_errors(ctrl_pdata, true);
+ rc = __mdss_dsi_dynamic_clock_switch(pdata, new_clk_rate);
+ if (!rc) {
+ struct mdss_dsi_ctrl_pdata *mctrl_pdata = NULL;
+ struct mdss_panel_info *mpinfo = NULL;
- if (phy_rev == DSI_PHY_REV_20) {
- rc = mdss_dsi_phy_calc_timing_param(pinfo, phy_rev,
- new_fps);
- if (rc) {
- pr_err("PHY calculations failed-%d\n", new_fps);
+ if (mdss_dsi_is_hw_config_split
+ (ctrl_pdata->shared_data) &&
+ mdss_dsi_is_ctrl_clk_master(ctrl_pdata))
goto end_update;
- }
- }
- rc = __mdss_dsi_dfps_calc_clks(pdata, new_fps);
- if (rc) {
- pr_err("error calculating clocks for %d\n", new_fps);
- goto error_clks;
- }
+ if (mdss_dsi_is_hw_config_split
+ (ctrl_pdata->shared_data) &&
+ mdss_dsi_is_ctrl_clk_slave(ctrl_pdata)) {
+ mctrl_pdata = mdss_dsi_get_ctrl_clk_master();
+ if (IS_ERR_OR_NULL(mctrl_pdata)) {
+ pr_err("Invalid mctrl_pdata\n");
+ goto end_update;
+ }
- rc = __mdss_dsi_dfps_update_clks(pdata, new_fps);
- if (rc) {
- pr_err("Dynamic refresh failed-%d\n", new_fps);
- goto error_dfps;
+ mpinfo = &mctrl_pdata->panel_data.panel_info;
+ }
+ /*
+ * update new fps that at this point is already
+ * updated in hw
+ */
+ pinfo->current_fps = new_fps;
+ if (mctrl_pdata && mpinfo)
+ mpinfo->current_fps = new_fps;
}
}
-
- return rc;
-error_dfps:
- if (__mdss_dsi_dfps_calc_clks(pdata, frame_rate_bkp))
- pr_err("error reverting clock calculations for %d\n",
- frame_rate_bkp);
-error_clks:
- if (mdss_dsi_phy_calc_timing_param(pinfo, phy_rev, frame_rate_bkp))
- pr_err("Unable to revert phy timing-%d\n", frame_rate_bkp);
end_update:
return rc;
}
@@ -2678,6 +2718,163 @@ static void mdss_dsi_timing_db_ctrl(struct mdss_dsi_ctrl_pdata *ctrl,
MDSS_DSI_CORE_CLK, MDSS_DSI_CLK_OFF);
}
+static struct mdss_dsi_ctrl_pdata *mdss_dsi_get_drvdata(struct device *dev)
+{
+ struct msm_fb_data_type *mfd;
+ struct mdss_panel_data *pdata;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+ struct fb_info *fbi = dev_get_drvdata(dev);
+
+ if (fbi) {
+ mfd = (struct msm_fb_data_type *)fbi->par;
+ pdata = dev_get_platdata(&mfd->pdev->dev);
+
+ ctrl_pdata = container_of(pdata,
+ struct mdss_dsi_ctrl_pdata, panel_data);
+ }
+
+ return ctrl_pdata;
+}
+
+static ssize_t supp_bitclk_list_sysfs_rda(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+ int i = 0;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = mdss_dsi_get_drvdata(dev);
+ struct mdss_panel_info *pinfo = NULL;
+
+ if (!ctrl_pdata) {
+ pr_err("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ pinfo = &ctrl_pdata->panel_data.panel_info;
+ if (!pinfo) {
+ pr_err("no panel connected\n");
+ return -ENODEV;
+ }
+
+ if (!pinfo->dynamic_bitclk) {
+ pr_err_once("%s: Dynamic bitclk not enabled for this panel\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ buf[0] = 0;
+ for (i = 0; i < pinfo->supp_bitclk_len; i++) {
+ if (ret > 0)
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
+ ",%d", pinfo->supp_bitclks[i]);
+ else
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
+ "%d", pinfo->supp_bitclks[i]);
+ }
+
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
+
+ return ret;
+}
+
+static ssize_t dynamic_bitclk_sysfs_wta(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int rc = 0, i = 0;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = mdss_dsi_get_drvdata(dev);
+ struct mdss_panel_info *pinfo = NULL;
+ int clk_rate = 0;
+
+ if (!ctrl_pdata) {
+ pr_err("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ pinfo = &ctrl_pdata->panel_data.panel_info;
+ if (!pinfo) {
+ pr_err("no panel connected\n");
+ return -ENODEV;
+ }
+
+ if (!pinfo->dynamic_bitclk) {
+ pr_err_once("%s: Dynamic bitclk not enabled for this panel\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (mdss_panel_is_power_off(pinfo->panel_power_state)) {
+ pr_err_once("%s: Panel powered off!\n", __func__);
+ return -EINVAL;
+ }
+
+ rc = kstrtoint(buf, 10, &clk_rate);
+ if (rc) {
+ pr_err("%s: kstrtoint failed. rc=%d\n", __func__, rc);
+ return rc;
+ }
+
+ for (i = 0; i < pinfo->supp_bitclk_len; i++) {
+ if (pinfo->supp_bitclks[i] == clk_rate)
+ break;
+ }
+ if (i == pinfo->supp_bitclk_len) {
+ pr_err("Requested bitclk: %d not supported\n", clk_rate);
+ return -EINVAL;
+ }
+
+ rc = __mdss_dsi_dynamic_clock_switch(&ctrl_pdata->panel_data,
+ clk_rate);
+ if (!rc && mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data)) {
+ struct mdss_dsi_ctrl_pdata *octrl =
+ mdss_dsi_get_other_ctrl(ctrl_pdata);
+ rc = __mdss_dsi_dynamic_clock_switch(&octrl->panel_data,
+ clk_rate);
+ if (rc)
+ pr_err("failed to switch DSI bitclk for sctrl\n");
+ } else if (rc) {
+ pr_err("failed to switch DSI bitclk\n");
+ }
+
+ return count;
+} /* dynamic_bitclk_sysfs_wta */
+
+static ssize_t dynamic_bitclk_sysfs_rda(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = mdss_dsi_get_drvdata(dev);
+ struct mdss_panel_info *pinfo = NULL;
+
+ if (!ctrl_pdata) {
+ pr_err("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ pinfo = &ctrl_pdata->panel_data.panel_info;
+ if (!pinfo) {
+ pr_err("no panel connected\n");
+ return -ENODEV;
+ }
+
+ ret = snprintf(buf, PAGE_SIZE, "%llu\n", pinfo->clk_rate);
+ pr_debug("%s: '%llu'\n", __func__, pinfo->clk_rate);
+
+ return ret;
+} /* dynamic_bitclk_sysfs_rda */
+
+static DEVICE_ATTR(dynamic_bitclk, S_IRUGO | S_IWUSR | S_IWGRP,
+ dynamic_bitclk_sysfs_rda, dynamic_bitclk_sysfs_wta);
+static DEVICE_ATTR(supported_bitclk, S_IRUGO, supp_bitclk_list_sysfs_rda, NULL);
+
+static struct attribute *dynamic_bitclk_fs_attrs[] = {
+ &dev_attr_dynamic_bitclk.attr,
+ &dev_attr_supported_bitclk.attr,
+ NULL,
+};
+
+static struct attribute_group mdss_dsi_fs_attrs_group = {
+ .attrs = dynamic_bitclk_fs_attrs,
+};
+
static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
int event, void *arg)
{
@@ -2844,6 +3041,14 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
ctrl_pdata->kobj = &fbi->dev->kobj;
ctrl_pdata->fb_node = fbi->node;
+ if (!mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) ||
+ (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) &&
+ mdss_dsi_is_ctrl_clk_master(ctrl_pdata))) {
+ if (sysfs_create_group(&fbi->dev->kobj,
+ &mdss_dsi_fs_attrs_group))
+ pr_err("failed to create DSI sysfs group\n");
+ }
+
if (IS_ENABLED(CONFIG_MSM_DBA) &&
pdata->panel_info.is_dba_panel) {
queue_delayed_work(ctrl_pdata->workq,
@@ -3392,7 +3597,7 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev)
pinfo = &(ctrl_pdata->panel_data.panel_info);
if (!(mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) &&
mdss_dsi_is_ctrl_clk_slave(ctrl_pdata)) &&
- pinfo->dynamic_fps) {
+ (pinfo->dynamic_fps || pinfo->dynamic_bitclk)) {
rc = mdss_dsi_shadow_clk_init(pdev, ctrl_pdata);
if (rc) {
@@ -4359,11 +4564,19 @@ int dsi_panel_device_register(struct platform_device *ctrl_pdev,
((mipi->mode == DSI_VIDEO_MODE)
? MIPI_VIDEO_PANEL : MIPI_CMD_PANEL);
- rc = mdss_dsi_clk_div_config(pinfo, mipi->frame_rate);
- if (rc) {
- pr_err("%s: unable to initialize the clk dividers\n", __func__);
- return rc;
+ pinfo->clk_rate = mdss_dsi_calc_bitclk(pinfo, mipi->frame_rate);
+ if (!pinfo->clk_rate) {
+ pr_err("%s: unable to calculate the DSI bit clock\n", __func__);
+ return -EINVAL;
}
+
+ pinfo->mipi.dsi_pclk_rate = mdss_dsi_get_pclk_rate(pinfo,
+ pinfo->clk_rate);
+ if (!pinfo->mipi.dsi_pclk_rate) {
+ pr_err("%s: unable to calculate the DSI pclk\n", __func__);
+ return -EINVAL;
+ }
+
ctrl_pdata->pclk_rate = mipi->dsi_pclk_rate;
clk_rate = pinfo->clk_rate;
do_div(clk_rate, 8U);
diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h
index 9847016fed29..900513931547 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.h
+++ b/drivers/video/fbdev/msm/mdss_dsi.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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
@@ -633,8 +633,8 @@ void disable_esd_thread(void);
void mdss_dsi_irq_handler_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata);
void mdss_dsi_set_tx_power_mode(int mode, struct mdss_panel_data *pdata);
-int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info,
- int frame_rate);
+u64 mdss_dsi_calc_bitclk(struct mdss_panel_info *panel_info, int frame_rate);
+u32 mdss_dsi_get_pclk_rate(struct mdss_panel_info *panel_info, u64 clk_rate);
int mdss_dsi_clk_refresh(struct mdss_panel_data *pdata, bool update_phy);
int mdss_dsi_link_clk_init(struct platform_device *pdev,
struct mdss_dsi_ctrl_pdata *ctrl_pdata);
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c
index dbd58f93e907..bf695ae0beaf 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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
@@ -1803,17 +1803,13 @@ static bool mdss_dsi_cmp_panel_reg_v2(struct mdss_dsi_ctrl_pdata *ctrl)
for (i = 0; i < ctrl->status_cmds.cmd_cnt; i++)
len += lenp[i];
- for (i = 0; i < len; i++) {
- pr_debug("[%i] return:0x%x status:0x%x\n",
- i, (unsigned int)ctrl->return_buf[i],
- (unsigned int)ctrl->status_value[j + i]);
- MDSS_XLOG(ctrl->ndx, ctrl->return_buf[i],
- ctrl->status_value[j + i]);
- j += len;
- }
-
for (j = 0; j < ctrl->groups; ++j) {
for (i = 0; i < len; ++i) {
+ pr_debug("[%i] return:0x%x status:0x%x\n",
+ i, ctrl->return_buf[i],
+ (unsigned int)ctrl->status_value[group + i]);
+ MDSS_XLOG(ctrl->ndx, ctrl->return_buf[i],
+ ctrl->status_value[group + i]);
if (ctrl->return_buf[i] !=
ctrl->status_value[group + i])
break;
@@ -2324,14 +2320,15 @@ static void mdss_dsi_parse_dfps_config(struct device_node *pan_node,
struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
const char *data;
- bool dynamic_fps;
+ bool dynamic_fps, dynamic_bitclk;
struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info);
+ int rc = 0;
dynamic_fps = of_property_read_bool(pan_node,
"qcom,mdss-dsi-pan-enable-dynamic-fps");
if (!dynamic_fps)
- return;
+ goto dynamic_bitclk;
pinfo->dynamic_fps = true;
data = of_get_property(pan_node, "qcom,mdss-dsi-pan-fps-update", NULL);
@@ -2361,6 +2358,31 @@ static void mdss_dsi_parse_dfps_config(struct device_node *pan_node,
pinfo->new_fps = pinfo->mipi.frame_rate;
pinfo->current_fps = pinfo->mipi.frame_rate;
+dynamic_bitclk:
+ dynamic_bitclk = of_property_read_bool(pan_node,
+ "qcom,mdss-dsi-pan-enable-dynamic-bitclk");
+ if (!dynamic_bitclk)
+ return;
+
+ of_find_property(pan_node, "qcom,mdss-dsi-dynamic-bitclk_freq",
+ &pinfo->supp_bitclk_len);
+ pinfo->supp_bitclk_len = pinfo->supp_bitclk_len/sizeof(u32);
+ if (pinfo->supp_bitclk_len < 1)
+ return;
+
+ pinfo->supp_bitclks = kzalloc((sizeof(u32) * pinfo->supp_bitclk_len),
+ GFP_KERNEL);
+ if (!pinfo->supp_bitclks)
+ return;
+
+ rc = of_property_read_u32_array(pan_node,
+ "qcom,mdss-dsi-dynamic-bitclk_freq", pinfo->supp_bitclks,
+ pinfo->supp_bitclk_len);
+ if (rc) {
+ pr_err("Error from dynamic bitclk freq u64 array read\n");
+ return;
+ }
+ pinfo->dynamic_bitclk = true;
return;
}
diff --git a/drivers/video/fbdev/msm/mdss_dsi_phy.c b/drivers/video/fbdev/msm/mdss_dsi_phy.c
index 2d2498643c3f..e8e903e6ce88 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_phy.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_phy.c
@@ -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
@@ -1034,15 +1034,10 @@ static void mdss_dsi_phy_update_timing_param_v3(struct mdss_panel_info *pinfo,
}
int mdss_dsi_phy_calc_timing_param(struct mdss_panel_info *pinfo, u32 phy_rev,
- u32 frate_hz)
+ u64 clk_rate)
{
struct dsi_phy_t_clk_param t_clk;
struct dsi_phy_timing t_param;
- int hsync_period;
- int vsync_period;
- unsigned long inter_num;
- uint32_t lane_config = 0;
- unsigned long x, y;
int rc = 0;
if (!pinfo) {
@@ -1050,30 +1045,12 @@ int mdss_dsi_phy_calc_timing_param(struct mdss_panel_info *pinfo, u32 phy_rev,
return -EINVAL;
}
- hsync_period = mdss_panel_get_htotal(pinfo, true);
- vsync_period = mdss_panel_get_vtotal(pinfo);
-
- inter_num = pinfo->bpp * frate_hz;
-
- if (pinfo->mipi.data_lane0)
- lane_config++;
- if (pinfo->mipi.data_lane1)
- lane_config++;
- if (pinfo->mipi.data_lane2)
- lane_config++;
- if (pinfo->mipi.data_lane3)
- lane_config++;
-
- x = mult_frac(vsync_period * hsync_period, inter_num, lane_config);
- y = rounddown(x, 1);
- t_clk.bitclk_mbps = rounddown(mult_frac(y, 1, 1000000), 1);
+ t_clk.bitclk_mbps = rounddown((uint32_t) div_u64(clk_rate, 1000000), 1);
t_clk.escclk_numer = ESC_CLK_MHZ;
t_clk.escclk_denom = ESCCLK_MMSS_CC_PREDIV;
t_clk.tlpx_numer_ns = TLPX_NUMER;
t_clk.treot_ns = TR_EOT;
- pr_debug("hperiod=%d, vperiod=%d, inter_num=%lu, lane_cfg=%d\n",
- hsync_period, vsync_period, inter_num, lane_config);
- pr_debug("x=%lu, y=%lu, bitrate=%d\n", x, y, t_clk.bitclk_mbps);
+ pr_debug("bitrate=%d\n", t_clk.bitclk_mbps);
rc = mdss_dsi_phy_initialize_defaults(&t_clk, &t_param, phy_rev);
if (rc) {
diff --git a/drivers/video/fbdev/msm/mdss_dsi_phy.h b/drivers/video/fbdev/msm/mdss_dsi_phy.h
index 03df17d81f69..b0f7d68556d5 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_phy.h
+++ b/drivers/video/fbdev/msm/mdss_dsi_phy.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
@@ -42,7 +42,7 @@ enum phy_mode {
* @frate_hz - Frame rate for which phy timing parameters are to be calculated.
*/
int mdss_dsi_phy_calc_timing_param(struct mdss_panel_info *pinfo, u32 phy_rev,
- u32 frate_hz);
+ u64 clk_rate);
/*
* mdss_dsi_phy_v3_init() - initialization sequence for DSI PHY rev v3
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index 6c4db0f1f5bd..1b408e2838d6 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -1,7 +1,7 @@
/*
* Core MDSS framebuffer driver.
*
- * Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
* Copyright (C) 2007 Google Incorporated
*
* This software is licensed under the terms of the GNU General Public
@@ -610,7 +610,7 @@ static ssize_t mdss_fb_get_panel_info(struct device *dev,
"red_chromaticity_x=%d\nred_chromaticity_y=%d\n"
"green_chromaticity_x=%d\ngreen_chromaticity_y=%d\n"
"blue_chromaticity_x=%d\nblue_chromaticity_y=%d\n"
- "panel_orientation=%d\n",
+ "panel_orientation=%d\ndyn_bitclk_en=%d\n",
pinfo->partial_update_enabled,
pinfo->roi_alignment.xstart_pix_align,
pinfo->roi_alignment.width_pix_align,
@@ -636,7 +636,7 @@ static ssize_t mdss_fb_get_panel_info(struct device *dev,
pinfo->hdr_properties.display_primaries[5],
pinfo->hdr_properties.display_primaries[6],
pinfo->hdr_properties.display_primaries[7],
- pinfo->panel_orientation);
+ pinfo->panel_orientation, pinfo->dynamic_bitclk);
return ret;
}
diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h
index acac672662c1..de3ff0c77625 100644
--- a/drivers/video/fbdev/msm/mdss_panel.h
+++ b/drivers/video/fbdev/msm/mdss_panel.h
@@ -805,6 +805,9 @@ struct mdss_panel_info {
int pwm_lpg_chan;
int pwm_period;
bool dynamic_fps;
+ bool dynamic_bitclk;
+ u32 *supp_bitclks;
+ u32 supp_bitclk_len;
bool ulps_feature_enabled;
bool ulps_suspend_enabled;
bool panel_ack_disabled;
diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
index bb3b4b3fa929..922c4440ba82 100644
--- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c
+++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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
@@ -1489,13 +1489,19 @@ int mdss_dsi_clk_refresh(struct mdss_panel_data *pdata, bool update_phy)
__func__, pinfo->mipi.frame_rate);
}
- rc = mdss_dsi_clk_div_config(&pdata->panel_info,
- pdata->panel_info.mipi.frame_rate);
- if (rc) {
- pr_err("%s: unable to initialize the clk dividers\n",
- __func__);
- return rc;
+ pinfo->clk_rate = mdss_dsi_calc_bitclk(pinfo, pinfo->mipi.frame_rate);
+ if (!pinfo->clk_rate) {
+ pr_err("%s: unable to calculate the DSI bit clock\n", __func__);
+ return -EINVAL;
}
+
+ pinfo->mipi.dsi_pclk_rate = mdss_dsi_get_pclk_rate(pinfo,
+ pinfo->clk_rate);
+ if (!pinfo->mipi.dsi_pclk_rate) {
+ pr_err("%s: unable to calculate the DSI pclk\n", __func__);
+ return -EINVAL;
+ }
+
ctrl_pdata->refresh_clk_rate = false;
ctrl_pdata->pclk_rate = pdata->panel_info.mipi.dsi_pclk_rate;
ctrl_pdata->byte_clk_rate = pdata->panel_info.clk_rate / 8;
@@ -1524,7 +1530,7 @@ int mdss_dsi_clk_refresh(struct mdss_panel_data *pdata, bool update_phy)
/* phy panel timing calaculation */
rc = mdss_dsi_phy_calc_timing_param(pinfo,
ctrl_pdata->shared_data->phy_rev,
- pinfo->mipi.frame_rate);
+ pdata->panel_info.clk_rate);
if (rc) {
pr_err("Error in calculating phy timings\n");
return rc;
@@ -1811,16 +1817,9 @@ bool is_diff_frame_rate(struct mdss_panel_info *panel_info,
return (frame_rate != panel_info->mipi.frame_rate);
}
-int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info,
- int frame_rate)
+static u8 mdss_dsi_get_lane_cnt(struct mdss_panel_info *panel_info)
{
- struct mdss_panel_data *pdata = container_of(panel_info,
- struct mdss_panel_data, panel_info);
- struct mdss_dsi_ctrl_pdata *ctrl_pdata = container_of(pdata,
- struct mdss_dsi_ctrl_pdata, panel_data);
- u64 h_period, v_period, clk_rate;
- u32 dsi_pclk_rate;
- u8 lanes = 0, bpp;
+ u8 lanes = 0;
if (!panel_info)
return -EINVAL;
@@ -1834,7 +1833,17 @@ int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info,
if (panel_info->mipi.data_lane0)
lanes += 1;
- switch (panel_info->mipi.dst_format) {
+ if (!lanes)
+ lanes = 1;
+
+ return lanes;
+}
+
+static u8 mdss_dsi_get_bpp(char dst_format)
+{
+ u8 bpp = 0;
+
+ switch (dst_format) {
case DSI_CMD_DST_FORMAT_RGB888:
case DSI_VIDEO_DST_FORMAT_RGB888:
case DSI_VIDEO_DST_FORMAT_RGB666_LOOSE:
@@ -1848,6 +1857,21 @@ int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info,
bpp = 3; /* Default format set to RGB888 */
break;
}
+ return bpp;
+}
+
+u64 mdss_dsi_calc_bitclk(struct mdss_panel_info *panel_info, int frame_rate)
+{
+ struct mdss_panel_data *pdata = container_of(panel_info,
+ struct mdss_panel_data, panel_info);
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = container_of(pdata,
+ struct mdss_dsi_ctrl_pdata, panel_data);
+ u64 h_period, v_period, clk_rate = 0;
+ u8 lanes = 0, bpp;
+
+ lanes = mdss_dsi_get_lane_cnt(panel_info);
+
+ bpp = mdss_dsi_get_bpp(panel_info->mipi.dst_format);
h_period = mdss_panel_get_htotal(panel_info, true);
if (panel_info->split_link_enabled)
@@ -1855,35 +1879,40 @@ int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info,
v_period = mdss_panel_get_vtotal(panel_info);
if (ctrl_pdata->refresh_clk_rate || is_diff_frame_rate(panel_info,
- frame_rate) || (!panel_info->clk_rate)) {
- if (lanes > 0) {
- panel_info->clk_rate = h_period * v_period * frame_rate
- * bpp * 8;
- do_div(panel_info->clk_rate, lanes);
- } else {
- pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__);
- panel_info->clk_rate =
- h_period * v_period * frame_rate * bpp * 8;
- }
+ frame_rate) || (!panel_info->clk_rate)) {
+ clk_rate = h_period * v_period * frame_rate * bpp * 8;
+ do_div(clk_rate, lanes);
+ } else if (panel_info->clk_rate) {
+ clk_rate = panel_info->clk_rate;
}
- if (panel_info->clk_rate == 0)
- panel_info->clk_rate = 454000000;
+ if (clk_rate == 0)
+ clk_rate = 454000000;
+
+ return clk_rate;
+}
+
+u32 mdss_dsi_get_pclk_rate(struct mdss_panel_info *panel_info, u64 clk_rate)
+{
+ u8 lanes = 0, bpp;
+ u32 pclk_rate = 0;
+
+ lanes = mdss_dsi_get_lane_cnt(panel_info);
+
+ bpp = mdss_dsi_get_bpp(panel_info->mipi.dst_format);
- clk_rate = panel_info->clk_rate;
do_div(clk_rate, 8 * bpp);
if (panel_info->split_link_enabled)
- dsi_pclk_rate = (u32) clk_rate *
+ pclk_rate = (u32) clk_rate *
panel_info->mipi.lanes_per_sublink;
else
- dsi_pclk_rate = (u32) clk_rate * lanes;
+ pclk_rate = (u32) clk_rate * lanes;
- if ((dsi_pclk_rate < 3300000) || (dsi_pclk_rate > 250000000))
- dsi_pclk_rate = 35000000;
- panel_info->mipi.dsi_pclk_rate = dsi_pclk_rate;
+ if ((pclk_rate < 3300000) || (pclk_rate > 250000000))
+ pclk_rate = 35000000;
- return 0;
+ return pclk_rate;
}
static bool mdss_dsi_is_ulps_req_valid(struct mdss_dsi_ctrl_pdata *ctrl,
diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c
index 27ec726e7a46..1ad7718c05d9 100644
--- a/fs/sdcardfs/main.c
+++ b/fs/sdcardfs/main.c
@@ -264,7 +264,7 @@ static int sdcardfs_read_super(struct vfsmount *mnt, struct super_block *sb,
pr_info("sdcardfs: dev_name -> %s\n", dev_name);
pr_info("sdcardfs: options -> %s\n", (char *)raw_data);
- pr_info("sdcardfs: mnt -> %p\n", mnt);
+ pr_info("sdcardfs: mnt -> %pK\n", mnt);
/* parse lower path */
err = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
diff --git a/fs/sdcardfs/super.c b/fs/sdcardfs/super.c
index cffcdb11cb8a..fa7d9d2c5c2b 100644
--- a/fs/sdcardfs/super.c
+++ b/fs/sdcardfs/super.c
@@ -144,7 +144,7 @@ static int sdcardfs_remount_fs2(struct vfsmount *mnt, struct super_block *sb,
pr_err("sdcardfs: remount flags 0x%x unsupported\n", *flags);
err = -EINVAL;
}
- pr_info("Remount options were %s for vfsmnt %p.\n", options, mnt);
+ pr_info("Remount options were %s for vfsmnt %pK.\n", options, mnt);
err = parse_options_remount(sb, options, *flags & ~MS_SILENT, mnt->data);
diff --git a/include/linux/qdsp6v2/audio-anc-dev-mgr.h b/include/linux/qdsp6v2/audio-anc-dev-mgr.h
index dfa6752bc31b..b0ece2dbb239 100644
--- a/include/linux/qdsp6v2/audio-anc-dev-mgr.h
+++ b/include/linux/qdsp6v2/audio-anc-dev-mgr.h
@@ -39,6 +39,8 @@ int msm_anc_dev_stop(void);
int msm_anc_dev_set_info(void *info_p, int32_t anc_cmd);
+int msm_anc_dev_get_info(void *info_p, int32_t anc_cmd);
+
int msm_anc_dev_create(struct platform_device *pdev);
int msm_anc_dev_destroy(struct platform_device *pdev);
diff --git a/include/linux/qdsp6v2/sdsp_anc.h b/include/linux/qdsp6v2/sdsp_anc.h
index 3b236e827e3d..5c1b7055c1d5 100644
--- a/include/linux/qdsp6v2/sdsp_anc.h
+++ b/include/linux/qdsp6v2/sdsp_anc.h
@@ -15,7 +15,6 @@
#include <sound/q6afe-v2.h>
#include <sound/apr_audio-v2.h>
-
#define AUD_MSVC_MODULE_AUDIO_DEV_RESOURCE_SHARE 0x0001028A
#define AUD_MSVC_PARAM_ID_PORT_SHARE_RESOURCE_CONFIG 0x00010297
#define AUD_MSVC_API_VERSION_SHARE_RESOURCE_CONFIG 0x1
@@ -23,8 +22,6 @@
#define AUD_MSVC_PARAM_ID_DEV_ANC_REFS_CONFIG 0x00010286
#define AUD_MSVC_API_VERSION_DEV_ANC_REFS_CONFIG 0x1
#define AUD_MSVC_MODULE_AUDIO_DEV_ANC_ALGO 0x00010234
-#define AUD_MSVC_PARAM_ID_PORT_ANC_ALGO_RPM 0x00010235
-#define AUD_MSVC_API_VERSION_DEV_ANC_ALGO_RPM 0x1
struct aud_msvc_port_param_data_v2 {
/* ID of the module to be configured.
@@ -148,7 +145,7 @@ struct aud_msvc_port_cmd_get_param_v2 {
} __packed;
struct aud_audioif_config_command {
- struct apr_hdr hdr;
+ struct apr_hdr hdr;
struct aud_msvc_port_cmd_set_param_v2 param;
struct aud_msvc_port_param_data_v2 pdata;
union afe_port_config port;
@@ -162,13 +159,6 @@ struct aud_msvc_param_id_dev_share_resource_cfg {
u32 lpm_length;
} __packed;
-
-struct aud_msvc_param_id_dev_anc_algo_rpm {
- u32 minor_version;
- u32 rpm;
-} __packed;
-
-
struct aud_msvc_param_id_dev_anc_refs_cfg {
u32 minor_version;
u16 port_id;
@@ -177,65 +167,20 @@ struct aud_msvc_param_id_dev_anc_refs_cfg {
u32 bit_width;
} __packed;
-
struct anc_share_resource_command {
- struct apr_hdr hdr;
+ struct apr_hdr hdr;
struct aud_msvc_port_cmd_set_param_v2 param;
struct aud_msvc_port_param_data_v2 pdata;
struct aud_msvc_param_id_dev_share_resource_cfg resource;
} __packed;
-
struct anc_config_ref_command {
- struct apr_hdr hdr;
+ struct apr_hdr hdr;
struct aud_msvc_port_cmd_set_param_v2 param;
struct aud_msvc_port_param_data_v2 pdata;
struct aud_msvc_param_id_dev_anc_refs_cfg refs;
} __packed;
-
-
-struct anc_set_rpm_command {
- struct apr_hdr hdr;
- struct aud_msvc_port_cmd_set_param_v2 param;
- struct aud_msvc_port_param_data_v2 pdata;
- struct aud_msvc_param_id_dev_anc_algo_rpm set_rpm;
-} __packed;
-
-struct anc_get_rpm_command {
- struct apr_hdr hdr;
- struct aud_msvc_port_cmd_get_param_v2 param;
- struct aud_msvc_port_param_data_v2 pdata;
- struct aud_msvc_param_id_dev_anc_algo_rpm get_rpm;
-} __packed;
-
-struct anc_get_rpm_resp {
- uint32_t status;
- struct aud_msvc_port_param_data_v2 pdata;
- struct aud_msvc_param_id_dev_anc_algo_rpm res_rpm;
-} __packed;
-
-#define AUD_MSVC_PARAM_ID_PORT_ANC_ALGO_BYPASS_MODE 0x0001029B
-
-#define AUD_MSVC_API_VERSION_DEV_ANC_ALGO_BYPASS_MODE 0x1
-
-#define AUD_MSVC_ANC_ALGO_BYPASS_MODE_NO 0x0
-#define AUD_MSVC_ANC_ALGO_BYPASS_MODE_REFS_TO_ANC_SPKR 0x1
-#define AUD_MSVC_ANC_ALGO_BYPASS_MODE_ANC_MIC_TO_ANC_SPKR 0x2
-#define AUD_MSVC_ANC_ALGO_BYPASS_MODE_REFS_MIXED_ANC_MIC_TO_ANC_SPKR 0x3
-
-struct aud_msvc_param_id_dev_anc_algo_bypass_mode {
- uint32_t minor_version;
- uint32_t bypass_mode;
-} __packed;
-
-struct anc_set_bypass_mode_command {
- struct apr_hdr hdr;
- struct aud_msvc_port_cmd_set_param_v2 param;
- struct aud_msvc_port_param_data_v2 pdata;
- struct aud_msvc_param_id_dev_anc_algo_bypass_mode set_bypass_mode;
-} __packed;
-
#define AUD_MSVC_PARAM_ID_PORT_ANC_ALGO_MODULE_ID 0x0001023A
struct aud_msvc_param_id_dev_anc_algo_module_id {
@@ -244,7 +189,7 @@ struct aud_msvc_param_id_dev_anc_algo_module_id {
} __packed;
struct anc_set_algo_module_id_command {
- struct apr_hdr hdr;
+ struct apr_hdr hdr;
struct aud_msvc_port_cmd_set_param_v2 param;
struct aud_msvc_port_param_data_v2 pdata;
struct aud_msvc_param_id_dev_anc_algo_module_id set_algo_module_id;
@@ -269,13 +214,37 @@ struct aud_msvc_param_id_dev_anc_mic_spkr_layout_info {
} __packed;
struct anc_set_mic_spkr_layout_info_command {
- struct apr_hdr hdr;
+ struct apr_hdr hdr;
struct aud_msvc_port_cmd_set_param_v2 param;
struct aud_msvc_port_param_data_v2 pdata;
struct aud_msvc_param_id_dev_anc_mic_spkr_layout_info
set_mic_spkr_layout;
} __packed;
+struct anc_set_algo_module_cali_data_command {
+ struct apr_hdr hdr;
+ struct aud_msvc_port_cmd_set_param_v2 param;
+ struct aud_msvc_port_param_data_v2 pdata;
+ /*
+ * calibration data payload followed
+ */
+} __packed;
+
+struct anc_get_algo_module_cali_data_command {
+ struct apr_hdr hdr;
+ struct aud_msvc_port_cmd_get_param_v2 param;
+ struct aud_msvc_port_param_data_v2 pdata;
+ /*
+ * calibration data payload followed
+ */
+} __packed;
+
+struct anc_get_algo_module_cali_data_resp {
+ uint32_t status;
+ struct aud_msvc_port_param_data_v2 pdata;
+ uint32_t payload[128];
+} __packed;
+
int anc_if_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port);
int anc_if_tdm_port_stop(u16 port_id);
@@ -286,15 +255,15 @@ int anc_if_share_resource(u16 port_id, u16 rddma_idx, u16 wrdma_idx,
int anc_if_config_ref(u16 port_id, u32 sample_rate, u32 bit_width,
u16 num_channel);
-int anc_if_set_rpm(u16 port_id, u32 rpm);
-
-int anc_if_set_bypass_mode(u16 port_id, u32 bypass_mode);
-
int anc_if_set_algo_module_id(u16 port_id, u32 module_id);
int anc_if_set_anc_mic_spkr_layout(u16 port_id,
struct aud_msvc_param_id_dev_anc_mic_spkr_layout_info *set_mic_spkr_layout_p);
+int anc_if_set_algo_module_cali_data(u16 port_id, void *data_p);
+
+int anc_if_get_algo_module_cali_data(u16 port_id, void *data_p);
+
int anc_if_shared_mem_map(void);
int anc_if_shared_mem_unmap(void);
diff --git a/include/net/cnss2.h b/include/net/cnss2.h
index e06f0b670d90..7ca407f6b606 100644
--- a/include/net/cnss2.h
+++ b/include/net/cnss2.h
@@ -192,6 +192,9 @@ extern void cnss_lock_pm_sem(struct device *dev);
extern void cnss_release_pm_sem(struct device *dev);
extern int cnss_auto_suspend(struct device *dev);
extern int cnss_auto_resume(struct device *dev);
+extern int cnss_pci_force_wake_request(struct device *dev);
+extern int cnss_pci_is_device_awake(struct device *dev);
+extern int cnss_pci_force_wake_release(struct device *dev);
extern int cnss_get_user_msi_assignment(struct device *dev, char *user_name,
int *num_vectors,
uint32_t *user_base_data,
diff --git a/include/uapi/linux/habmmid.h b/include/uapi/linux/habmmid.h
index 4f79506dd971..1845c72c9e60 100644
--- a/include/uapi/linux/habmmid.h
+++ b/include/uapi/linux/habmmid.h
@@ -29,7 +29,8 @@
#define MM_VID_START 500
#define MM_VID 501
-#define MM_VID_END 502
+#define MM_VID_2 502
+#define MM_VID_END 503
#define MM_MISC_START 600
#define MM_MISC 601
@@ -37,10 +38,7 @@
#define MM_QCPE_START 700
#define MM_QCPE_VM1 701
-#define MM_QCPE_VM2 702
-#define MM_QCPE_VM3 703
-#define MM_QCPE_VM4 704
-#define MM_QCPE_END 705
+#define MM_QCPE_END 702
#define MM_CLK_START 800
#define MM_CLK_VM1 801
diff --git a/include/uapi/linux/msm_audio_anc.h b/include/uapi/linux/msm_audio_anc.h
index d628f7ce9267..87701fd8ee3a 100644
--- a/include/uapi/linux/msm_audio_anc.h
+++ b/include/uapi/linux/msm_audio_anc.h
@@ -21,6 +21,8 @@
/* room for ANC_CMD define extend */
#define ANC_CMD_MAX 0xFF
+#define ANC_CALIBRATION_PAYLOAD_SIZE_MAX 100
+
struct audio_anc_header {
int32_t data_size;
int32_t version;
@@ -35,14 +37,23 @@ struct audio_anc_rpm_info {
struct audio_anc_bypass_mode {
int32_t mode;
};
-
struct audio_anc_algo_module_info {
int32_t module_id;
};
+struct audio_anc_algo_calibration_header {
+ uint32_t module_id;
+ uint32_t param_id;
+ uint32_t payload_size;
+};
+
+struct audio_anc_algo_calibration_body {
+ int32_t payload[ANC_CALIBRATION_PAYLOAD_SIZE_MAX];
+};
+
struct audio_anc_algo_calibration_info {
- int32_t payload_size;
- /* num bytes of payload specificed in payload_size followed */
+ struct audio_anc_algo_calibration_header cali_header;
+ struct audio_anc_algo_calibration_body cali_body;
};
union audio_anc_data {
diff --git a/include/uapi/linux/msm_kgsl.h b/include/uapi/linux/msm_kgsl.h
index 13bb8b79359a..005fb8284524 100644
--- a/include/uapi/linux/msm_kgsl.h
+++ b/include/uapi/linux/msm_kgsl.h
@@ -322,6 +322,8 @@ enum kgsl_timestamp_type {
#define KGSL_PROP_DEVICE_QDSS_STM 0x19
#define KGSL_PROP_DEVICE_QTIMER 0x20
#define KGSL_PROP_IB_TIMEOUT 0x21
+#define KGSL_PROP_SECURE_BUFFER_ALIGNMENT 0x23
+#define KGSL_PROP_SECURE_CTXT_SUPPORT 0x24
struct kgsl_shadowprop {
unsigned long gpuaddr;