Files
bananarchy/patches/kernel/0001-msm8909-qdsp6-voice-sound-nokia-argon-6.12.patch
T
2026-10-19 09:23:54 +03:00

1574 lines
47 KiB
Diff

From b6d30de989bc00081e7a6ca5bb15ab0eafc4642e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Otto=20Pfl=C3=BCger?= <otto.pflueger@abscue.de>
Date: Wed, 28 Jun 2023 14:47:49 +0200
Subject: [PATCH 01/11] ASoC: qcom: q6core: expose ADSP core firmware version
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add a q6core_get_adsp_version() function that returns the version of the
ADSP firmware (2.6, 2.7 or 2.8), also known as the AVS version (see [1]
in downstream kernel).
Some APIs differ between these versions, e.g. the AFE clock APIs.
[1]: https://github.com/msm8916-mainline/linux-downstream/blob/LA.BR.1.2.9.1_rb1.5/sound/soc/msm/qdsp6v2/q6core.c#L193
Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
sound/soc/qcom/qdsp6/q6core.c | 65 +++++++++++++++++++++++++++++++++++
sound/soc/qcom/qdsp6/q6core.h | 9 +++++
2 files changed, 74 insertions(+)
diff --git a/sound/soc/qcom/qdsp6/q6core.c b/sound/soc/qcom/qdsp6/q6core.c
index 49cfb32cd20917..855ab4ff1e598a 100644
--- a/sound/soc/qcom/qdsp6/q6core.c
+++ b/sound/soc/qcom/qdsp6/q6core.c
@@ -20,6 +20,9 @@
#define AVCS_CMDRSP_ADSP_EVENT_GET_STATE 0x0001290D
#define AVCS_GET_VERSIONS 0x00012905
#define AVCS_GET_VERSIONS_RSP 0x00012906
+#define AVCS_CMDRSP_Q6_ID_2_6 0x00040000
+#define AVCS_CMDRSP_Q6_ID_2_7 0x00040001
+#define AVCS_CMDRSP_Q6_ID_2_8 0x00040002
#define AVCS_CMD_GET_FWK_VERSION 0x001292c
#define AVCS_CMDRSP_GET_FWK_VERSION 0x001292d
@@ -63,6 +66,7 @@ struct q6core {
bool get_state_supported;
bool get_version_supported;
bool is_version_requested;
+ enum q6core_version adsp_version;
};
static struct q6core *g_core;
@@ -108,6 +112,14 @@ static int q6core_callback(struct apr_device *adev, struct apr_resp_pkt *data)
if (!core->fwk_version)
return -ENOMEM;
+ /*
+ * Since GET_VERSIONS is not called when GET_FWK_VERSION
+ * is successful and these commands may return completely
+ * different versions, assume that the version is 2.8 here.
+ * Older versions do not support GET_FWK_VERSION and we do
+ * not care if the version is newer than 2.8.
+ */
+ core->adsp_version = Q6_ADSP_VERSION_2_8;
core->fwk_version_supported = true;
core->resp_received = true;
@@ -115,6 +127,7 @@ static int q6core_callback(struct apr_device *adev, struct apr_resp_pkt *data)
}
case AVCS_GET_VERSIONS_RSP: {
struct avcs_cmdrsp_get_version *v;
+ int i;
v = data->payload;
@@ -125,6 +138,32 @@ static int q6core_callback(struct apr_device *adev, struct apr_resp_pkt *data)
if (!core->svc_version)
return -ENOMEM;
+ for (i = 0; i < g_core->svc_version->num_services; i++) {
+ struct avcs_svc_info *info;
+
+ info = &g_core->svc_version->svc_api_info[i];
+ if (info->service_id != APR_SVC_ADSP_CORE)
+ continue;
+
+ switch (info->version) {
+ case AVCS_CMDRSP_Q6_ID_2_6:
+ core->adsp_version = Q6_ADSP_VERSION_2_6;
+ break;
+ case AVCS_CMDRSP_Q6_ID_2_7:
+ core->adsp_version = Q6_ADSP_VERSION_2_7;
+ break;
+ case AVCS_CMDRSP_Q6_ID_2_8:
+ core->adsp_version = Q6_ADSP_VERSION_2_8;
+ break;
+ default:
+ dev_err(&adev->dev, "Unknown AVS version 0x%08x\n",
+ info->version);
+ break;
+ }
+
+ break;
+ }
+
core->get_version_supported = true;
core->resp_received = true;
@@ -293,6 +332,31 @@ int q6core_get_svc_api_info(int svc_id, struct q6core_svc_api_info *ainfo)
}
EXPORT_SYMBOL_GPL(q6core_get_svc_api_info);
+/**
+ * q6core_get_adsp_version() - Get the core version number.
+ *
+ * Return: version code or Q6_ADSP_VERSION_UNKNOWN on failure
+ */
+enum q6core_version q6core_get_adsp_version(void)
+{
+ int ret;
+
+ if (!g_core)
+ return Q6_ADSP_VERSION_UNKNOWN;
+
+ mutex_lock(&g_core->lock);
+ if (!g_core->is_version_requested) {
+ if (q6core_get_fwk_versions(g_core) == -ENOTSUPP)
+ q6core_get_svc_versions(g_core);
+ g_core->is_version_requested = true;
+ }
+ ret = g_core->adsp_version;
+ mutex_unlock(&g_core->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(q6core_get_adsp_version);
+
/**
* q6core_is_adsp_ready() - Get status of adsp
*
@@ -334,6 +398,7 @@ static int q6core_probe(struct apr_device *adev)
dev_set_drvdata(&adev->dev, g_core);
mutex_init(&g_core->lock);
+ g_core->adsp_version = Q6_ADSP_VERSION_UNKNOWN;
g_core->adev = adev;
init_waitqueue_head(&g_core->wait);
return 0;
diff --git a/sound/soc/qcom/qdsp6/q6core.h b/sound/soc/qcom/qdsp6/q6core.h
index 4105b1d730be88..472e06bf8efc79 100644
--- a/sound/soc/qcom/qdsp6/q6core.h
+++ b/sound/soc/qcom/qdsp6/q6core.h
@@ -9,7 +9,16 @@ struct q6core_svc_api_info {
uint32_t api_branch_version;
};
+/* Versions must be in order! */
+enum q6core_version {
+ Q6_ADSP_VERSION_UNKNOWN,
+ Q6_ADSP_VERSION_2_6,
+ Q6_ADSP_VERSION_2_7,
+ Q6_ADSP_VERSION_2_8,
+};
+
bool q6core_is_adsp_ready(void);
+enum q6core_version q6core_get_adsp_version(void);
int q6core_get_svc_api_info(int svc_id, struct q6core_svc_api_info *ainfo);
#endif /* __Q6CORE_H__ */
From c8d723a0e008f875858c413348e2160ba343f47e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Otto=20Pfl=C3=BCger?= <otto.pflueger@abscue.de>
Date: Sun, 29 Oct 2023 15:33:26 +0100
Subject: [PATCH 02/11] ASoC: qcom: q6afe: provide fallback for digital codec
clock
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When q6afe is used as a clock provider through q6afe-clocks.c, it uses
an interface for setting clocks that is not present in older firmware
versions. However, using Q6AFE_LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE
as the codec MCLK in the device tree can be useful on older platforms
too. Provide a fallback that sets this clock using the old method when
an old firmware version is detected.
MSM8916 did not need this because of a workaround that controls this
clock directly through the GCC driver, but newer SoCs do not have this
clock in their GCC drivers because it is meant to be controlled by the
DSP.
Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
sound/soc/qcom/qdsp6/q6afe.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c
index 7b59d514b432a2..ff3f7e12112aab 100644
--- a/sound/soc/qcom/qdsp6/q6afe.c
+++ b/sound/soc/qcom/qdsp6/q6afe.c
@@ -1203,6 +1203,32 @@ int q6afe_set_lpass_clock(struct device *dev, int clk_id, int attri,
struct q6afe *afe = dev_get_drvdata(dev->parent);
struct afe_clk_set cset = {0,};
+ /*
+ * v2 clocks specified in the device tree may not be supported by the
+ * firmware. If this is the digital codec core clock, fall back to the
+ * old method for setting it.
+ */
+ if (q6core_get_adsp_version() < Q6_ADSP_VERSION_2_7) {
+ struct q6afe_port *port;
+ struct afe_digital_clk_cfg dcfg = {0,};
+ int ret;
+
+ if (clk_id != Q6AFE_LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE)
+ return -EINVAL;
+
+ port = q6afe_port_get_from_id(dev, PRIMARY_MI2S_RX);
+ if (IS_ERR(port))
+ return PTR_ERR(port);
+
+ dcfg.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG;
+ dcfg.clk_val = freq;
+ dcfg.clk_root = 5;
+ ret = q6afe_set_digital_codec_core_clock(port, &dcfg);
+
+ q6afe_port_put(port);
+ return ret;
+ }
+
cset.clk_set_minor_version = AFE_API_VERSION_CLOCK_SET;
cset.clk_id = clk_id;
cset.clk_freq_in_hz = freq;
From a281e48154f357b119cb784ea5c2b338eff9a593 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Otto=20Pfl=C3=BCger?= <otto.pflueger@abscue.de>
Date: Sun, 29 Oct 2023 15:52:32 +0100
Subject: [PATCH 03/11] ASoC: qcom: q6afe-dai: check ADSP version when setting
sysclk
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Some older DSP firmware versions only provide AFE_PARAM_ID_*_CLK_CONFIG
requests for setting clocks, while newer ones only provide the
incompatible AFE_PARAM_ID_CLOCK_SET. The q6afe driver implements both,
but requires different clock IDs for the different firmware versions.
Implement the LPAIF_*_CLK clocks using newer clock IDs when the DSP
firmware does not support the old clocks so that users don't have to
care about the firmware version when setting clocks.
Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
sound/soc/qcom/qdsp6/q6afe-dai.c | 98 +++++++++++++++++++++++++++-----
1 file changed, 84 insertions(+), 14 deletions(-)
diff --git a/sound/soc/qcom/qdsp6/q6afe-dai.c b/sound/soc/qcom/qdsp6/q6afe-dai.c
index 0f47aadaabe171..6d842d20b70198 100644
--- a/sound/soc/qcom/qdsp6/q6afe-dai.c
+++ b/sound/soc/qcom/qdsp6/q6afe-dai.c
@@ -14,6 +14,7 @@
#include <sound/pcm_params.h>
#include "q6dsp-lpass-ports.h"
#include "q6dsp-common.h"
+#include "q6core.h"
#include "q6afe.h"
@@ -484,36 +485,105 @@ static int q6slim_set_channel_map(struct snd_soc_dai *dai,
return 0;
}
+static int q6afe_get_bit_clk_id(unsigned int dai_id)
+{
+ switch (dai_id) {
+ case PRIMARY_MI2S_RX:
+ case PRIMARY_MI2S_TX:
+ return Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT;
+ case SECONDARY_MI2S_RX:
+ case SECONDARY_MI2S_TX:
+ return Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT;
+ case TERTIARY_MI2S_RX:
+ case TERTIARY_MI2S_TX:
+ return Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT;
+ case QUATERNARY_MI2S_RX:
+ case QUATERNARY_MI2S_TX:
+ return Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT;
+ case QUINARY_MI2S_RX:
+ case QUINARY_MI2S_TX:
+ return Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT;
+
+ case PRIMARY_TDM_RX_0 ... PRIMARY_TDM_TX_7:
+ return Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT;
+ case SECONDARY_TDM_RX_0 ... SECONDARY_TDM_TX_7:
+ return Q6AFE_LPASS_CLK_ID_SEC_TDM_IBIT;
+ case TERTIARY_TDM_RX_0 ... TERTIARY_TDM_TX_7:
+ return Q6AFE_LPASS_CLK_ID_TER_TDM_IBIT;
+ case QUATERNARY_TDM_RX_0 ... QUATERNARY_TDM_TX_7:
+ return Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT;
+ case QUINARY_TDM_RX_0 ... QUINARY_TDM_TX_7:
+ return Q6AFE_LPASS_CLK_ID_QUIN_TDM_IBIT;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int q6afe_get_osr_clk_id(unsigned int dai_id)
+{
+ switch (dai_id) {
+ case QUINARY_MI2S_RX:
+ case QUINARY_MI2S_TX:
+ return Q6AFE_LPASS_CLK_ID_QUI_MI2S_OSR;
+
+ case QUINARY_TDM_RX_0 ... QUINARY_TDM_TX_7:
+ return Q6AFE_LPASS_CLK_ID_QUIN_TDM_OSR;
+
+ default:
+ return -EINVAL;
+ }
+}
+
static int q6afe_mi2s_set_sysclk(struct snd_soc_dai *dai,
int clk_id, unsigned int freq, int dir)
{
struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
struct q6afe_port *port = dai_data->port[dai->id];
+ int clk_src;
+ int clk_root;
+ bool use_new_clks = q6core_get_adsp_version() >= Q6_ADSP_VERSION_2_7;
switch (clk_id) {
case LPAIF_DIG_CLK:
- return q6afe_port_set_sysclk(port, clk_id, 0, 5, freq, dir);
+ if (use_new_clks) {
+ clk_src = Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO;
+ clk_root = Q6AFE_LPASS_CLK_ROOT_DEFAULT;
+ clk_id = Q6AFE_LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE;
+ } else {
+ clk_src = 0;
+ clk_root = 5;
+ }
+ break;
case LPAIF_BIT_CLK:
case LPAIF_OSR_CLK:
- return q6afe_port_set_sysclk(port, clk_id,
- Q6AFE_LPASS_CLK_SRC_INTERNAL,
- Q6AFE_LPASS_CLK_ROOT_DEFAULT,
- freq, dir);
+ if (use_new_clks) {
+ clk_src = Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO;
+ clk_root = Q6AFE_LPASS_CLK_ROOT_DEFAULT;
+ if (clk_id == LPAIF_OSR_CLK)
+ clk_id = q6afe_get_osr_clk_id(dai->id);
+ else
+ clk_id = q6afe_get_bit_clk_id(dai->id);
+ } else {
+ clk_src = Q6AFE_LPASS_CLK_SRC_INTERNAL;
+ clk_root = Q6AFE_LPASS_CLK_ROOT_DEFAULT;
+ }
+ break;
case Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT ... Q6AFE_LPASS_CLK_ID_QUI_MI2S_OSR:
case Q6AFE_LPASS_CLK_ID_MCLK_1 ... Q6AFE_LPASS_CLK_ID_INT_MCLK_1:
case Q6AFE_LPASS_CLK_ID_WSA_CORE_MCLK ... Q6AFE_LPASS_CLK_ID_VA_CORE_2X_MCLK:
- return q6afe_port_set_sysclk(port, clk_id,
- Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
- Q6AFE_LPASS_CLK_ROOT_DEFAULT,
- freq, dir);
+ clk_src = Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO;
+ clk_root = Q6AFE_LPASS_CLK_ROOT_DEFAULT;
+ break;
case Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT ... Q6AFE_LPASS_CLK_ID_QUIN_TDM_EBIT:
- return q6afe_port_set_sysclk(port, clk_id,
- Q6AFE_LPASS_CLK_ATTRIBUTE_INVERT_COUPLE_NO,
- Q6AFE_LPASS_CLK_ROOT_DEFAULT,
- freq, dir);
+ clk_src = Q6AFE_LPASS_CLK_ATTRIBUTE_INVERT_COUPLE_NO;
+ clk_root = Q6AFE_LPASS_CLK_ROOT_DEFAULT;
+ break;
+ default:
+ return 0;
}
- return 0;
+ return q6afe_port_set_sysclk(port, clk_id, clk_src, clk_root, freq, dir);
}
static const struct snd_soc_dapm_route q6afe_dapm_routes[] = {
From 5edd23fb20aa78cb8456ca2cd412f0322d4071ca Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Otto=20Pfl=C3=BCger?= <otto.pflueger@abscue.de>
Date: Sat, 14 Oct 2023 16:29:16 +0200
Subject: [PATCH 04/11] ASoC: qcom: q6afe: remove "port already open" error
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The clock fallback for older firmware versions now represents a use case
for having multiple references to a port. Stop logging an error when a
port is requested more than once because this does not indicate a problem
anymore and causes unnecessary spam in dmesg.
Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
sound/soc/qcom/qdsp6/q6afe.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c
index ff3f7e12112aab..7b5d90e1452932 100644
--- a/sound/soc/qcom/qdsp6/q6afe.c
+++ b/sound/soc/qcom/qdsp6/q6afe.c
@@ -1777,10 +1777,8 @@ struct q6afe_port *q6afe_port_get_from_id(struct device *dev, int id)
/* if port is multiple times bind/unbind before callback finishes */
port = q6afe_find_port(afe, id);
- if (port) {
- dev_err(dev, "AFE Port already open\n");
+ if (port)
return port;
- }
port_id = port_maps[id].port_id;
From d813b49d565ccc7a0247b746afc8149a82cd73c7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Otto=20Pfl=C3=BCger?= <otto.pflueger@abscue.de>
Date: Thu, 29 Jun 2023 13:51:20 +0200
Subject: [PATCH 05/11] arm64: dts: msm8916: use q6afe-clocks for digital codec
mclk
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
(breaks audio with dsp disabled, but useful for testing)
Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
arch/arm64/boot/dts/qcom/msm8916.dtsi | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 16ebf5349c9596..2698e5fff1ae6a 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -13,6 +13,7 @@
#include <dt-bindings/reset/qcom,gcc-msm8916.h>
#include <dt-bindings/soc/qcom,apr.h>
#include <dt-bindings/soc/qcom,memshare.h>
+#include <dt-bindings/sound/qcom,q6afe.h>
#include <dt-bindings/thermal/thermal.h>
/ {
@@ -2055,6 +2056,11 @@
compatible = "qcom,q6afe";
reg = <APR_SVC_AFE>;
+ q6afecc: clock-controller {
+ compatible = "qcom,q6afe-clocks";
+ #clock-cells = <2>;
+ };
+
q6afedai: dais {
compatible = "qcom,q6afe-dais";
#address-cells = <1>;
@@ -2168,11 +2174,14 @@
lpass_codec: audio-codec@771c000 {
compatible = "qcom,msm8916-wcd-digital-codec";
reg = <0x0771c000 0x400>;
- clocks = <&gcc GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK>,
- <&gcc GCC_CODEC_DIGCODEC_CLK>;
+ clocks = <&xo_board>,
+ <&q6afecc LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE
+ LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
clock-names = "ahbix-clk", "mclk";
#sound-dai-cells = <1>;
status = "disabled";
+ assigned-clocks = <&q6afecc LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+ assigned-clock-rates = <9600000>;
};
sdhc_1: mmc@7824900 {
From 85b826377e27a2a4b02a23823d28556bd0a406f6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Otto=20Pfl=C3=BCger?= <otto.pflueger@abscue.de>
Date: Tue, 7 Mar 2023 18:44:50 +0100
Subject: [PATCH 06/11] ARM: dts: qcom: pm8909: add audio codec
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
arch/arm/boot/dts/qcom/qcom-pm8909.dtsi | 38 +++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/arch/arm/boot/dts/qcom/qcom-pm8909.dtsi b/arch/arm/boot/dts/qcom/qcom-pm8909.dtsi
index b632a1883d7732..00862a9a6eda24 100644
--- a/arch/arm/boot/dts/qcom/qcom-pm8909.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-pm8909.dtsi
@@ -142,5 +142,43 @@
reg = <0xc000>;
status = "disabled";
};
+
+ wcd_codec: audio-codec@f000 {
+ compatible = "qcom,pm8916-wcd-analog-codec";
+ reg = <0xf000>;
+ reg-names = "pmic-codec-core";
+ interrupt-parent = <&spmi_bus>;
+ interrupts = <0x1 0xf0 0x0 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x1 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x2 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x3 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x4 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x5 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x6 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x7 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x0 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x1 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x2 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x3 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x4 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x5 IRQ_TYPE_NONE>;
+ interrupt-names = "cdc_spk_cnp_int",
+ "cdc_spk_clip_int",
+ "cdc_spk_ocp_int",
+ "mbhc_ins_rem_det1",
+ "mbhc_but_rel_det",
+ "mbhc_but_press_det",
+ "mbhc_ins_rem_det",
+ "mbhc_switch_int",
+ "cdc_ear_ocp_int",
+ "cdc_hphr_ocp_int",
+ "cdc_hphl_ocp_det",
+ "cdc_ear_cnp_int",
+ "cdc_hphr_cnp_int",
+ "cdc_hphl_cnp_int";
+ #sound-dai-cells = <1>;
+
+ status = "disabled";
+ };
};
};
From a9017ac6cb931d1bfd5aebcc822ad5bf973e0808 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Otto=20Pfl=C3=BCger?= <otto.pflueger@abscue.de>
Date: Tue, 7 Mar 2023 18:45:09 +0100
Subject: [PATCH 07/11] ARM: dts: qcom: msm8909: add sound
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
arch/arm/boot/dts/qcom/qcom-msm8909.dtsi | 110 +++++++++++++++++++++++
1 file changed, 110 insertions(+)
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8909.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8909.dtsi
index 54732effd2d30c..4c2d64531c7dc5 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8909.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-msm8909.dtsi
@@ -9,6 +9,10 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/qcom-rpmpd.h>
#include <dt-bindings/thermal/thermal.h>
+#include <dt-bindings/soc/qcom,apr.h>
+#include <dt-bindings/sound/qcom,q6afe.h>
+#include <dt-bindings/sound/qcom,q6asm.h>
+#include <dt-bindings/sound/qcom,q6voice.h>
/ {
#address-cells = <1>;
@@ -807,6 +811,25 @@
drive-strength = <6>;
bias-pull-up;
};
+
+ cdc-pdm-lines {
+ cdc_pdm_lines_act: pdm-lines-on {
+ pins = "gpio59", "gpio60", "gpio61",
+ "gpio62", "gpio63", "gpio64";
+ function = "cdc_pdm0";
+
+ drive-strength = <8>;
+ bias-disable;
+ };
+ cdc_pdm_lines_sus: pdm-lines-off {
+ pins = "gpio59", "gpio60", "gpio61",
+ "gpio62", "gpio63", "gpio64";
+ function = "cdc_pdm0";
+
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
};
gcc: clock-controller@1800000 {
@@ -924,9 +947,96 @@
qcom,remote-pid = <1>;
label = "hexagon";
+
+ apr: apr {
+ compatible = "qcom,apr-v2";
+ qcom,smd-channels = "apr_audio_svc";
+ qcom,apr-domain = <APR_DOMAIN_ADSP>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+
+ apr-service@3 {
+ reg = <APR_SVC_ADSP_CORE>;
+ compatible = "qcom,q6core";
+ };
+
+ q6afe: apr-service@4 {
+ compatible = "qcom,q6afe";
+ reg = <APR_SVC_AFE>;
+ q6afedai: dais {
+ compatible = "qcom,q6afe-dais";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #sound-dai-cells = <1>;
+ };
+ q6afecc: clock-controller {
+ compatible = "qcom,q6afe-clocks";
+ #clock-cells = <2>;
+ };
+ };
+
+ q6asm: apr-service@7 {
+ compatible = "qcom,q6asm";
+ reg = <APR_SVC_ASM>;
+ q6asmdai: dais {
+ compatible = "qcom,q6asm-dais";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #sound-dai-cells = <1>;
+ };
+ };
+
+ q6adm: apr-service@8 {
+ compatible = "qcom,q6adm";
+ reg = <APR_SVC_ADM>;
+ q6routing: routing {
+ compatible = "qcom,q6adm-routing";
+ #sound-dai-cells = <0>;
+ };
+ };
+
+ q6mvm: apr-service@9 {
+ compatible = "qcom,q6mvm";
+ reg = <APR_SVC_ADSP_MVM>;
+
+ q6voicedai: dais {
+ compatible = "qcom,q6voice-dais";
+ #sound-dai-cells = <1>;
+ };
+ };
+
+ q6cvs: apr-service@a {
+ compatible = "qcom,q6cvs";
+ reg = <APR_SVC_ADSP_CVS>;
+ };
+
+ q6cvp: apr-service@b {
+ compatible = "qcom,q6cvp";
+ reg = <APR_SVC_ADSP_CVP>;
+ };
+ };
};
};
+ sound: sound@7702000 {
+ status = "disabled";
+ compatible = "qcom,msm8916-qdsp6-sndcard";
+ reg = <0x07702000 0x4>, <0x07702004 0x4>;
+ reg-names = "mic-iomux", "spkr-iomux";
+ };
+
+ lpass_codec: audio-codec@771c000 {
+ compatible = "qcom,msm8916-wcd-digital-codec";
+ reg = <0x0771c000 0x400>;
+ clocks = <&xo_board>,
+ <&q6afecc LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+ clock-names = "ahbix-clk", "mclk";
+ assigned-clocks = <&q6afecc LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+ assigned-clock-rates = <9600000>;
+ #sound-dai-cells = <1>;
+ };
+
sdhc_1: sdhci@7824000 {
compatible = "qcom,msm8916-sdhci", "qcom,sdhci-msm-v4";
reg = <0x07824900 0x11c>, <0x07824000 0x800>;
From 7bdef6582b207977d13bae286b2658ce9da010ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Otto=20Pfl=C3=BCger?= <otto.pflueger@abscue.de>
Date: Tue, 7 Mar 2023 18:46:14 +0100
Subject: [PATCH 08/11] ARM: dts: qcom: msm8905-nokia-argon: add sound
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
.../dts/qcom/qcom-msm8905-nokia-argon.dts | 149 ++++++++++++++++++
1 file changed, 149 insertions(+)
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8905-nokia-argon.dts b/arch/arm/boot/dts/qcom/qcom-msm8905-nokia-argon.dts
index 724c5be8c5b06a..dd0b6391f2505e 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8905-nokia-argon.dts
+++ b/arch/arm/boot/dts/qcom/qcom-msm8905-nokia-argon.dts
@@ -6,6 +6,9 @@
#include <dt-bindings/leds/common.h>
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
#include <dt-bindings/pinctrl/qcom,pmic-mpp.h>
+#include <dt-bindings/sound/qcom,q6afe.h>
+#include <dt-bindings/sound/qcom,q6asm.h>
+#include <dt-bindings/sound/qcom,q6voice.h>
/ {
model = "Nokia 8110 4G";
@@ -154,6 +157,10 @@
};
};
+&apr {
+ status = "okay";
+};
+
&blsp_spi5 {
status = "okay";
@@ -224,6 +231,37 @@
status = "okay";
};
+&q6afedai {
+ dai@16 {
+ reg = <PRIMARY_MI2S_RX>;
+ qcom,sd-lines = <0 1>;
+ };
+ dai@20 {
+ reg = <TERTIARY_MI2S_TX>;
+ qcom,sd-lines = <0 1>;
+ };
+};
+
+&q6asmdai {
+ dai@0 {
+ reg = <0>;
+ direction = <Q6ASM_DAI_RX>;
+ };
+ dai@1 {
+ reg = <1>;
+ direction = <Q6ASM_DAI_TX>;
+ };
+ dai@2 {
+ reg = <2>;
+ direction = <Q6ASM_DAI_RX>;
+ };
+ dai@3 {
+ reg = <3>;
+ direction = <Q6ASM_DAI_RX>;
+ is-compress-dai;
+ };
+};
+
&sdhc_1 {
status = "okay";
};
@@ -233,6 +271,103 @@
status = "okay";
};
+&sound {
+ status = "okay";
+ model = "msm8916";
+
+ audio-routing =
+ "AMIC1", "MIC BIAS External1",
+ "AMIC2", "MIC BIAS Internal2",
+ "AMIC3", "MIC BIAS External1";
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&cdc_pdm_lines_act>;
+ pinctrl-1 = <&cdc_pdm_lines_sus>;
+
+ dai-link-multimedia1 {
+ link-name = "MultiMedia1";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
+ };
+ };
+
+ dai-link-multimedia2 {
+ link-name = "MultiMedia2";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA2>;
+ };
+ };
+
+ dai-link-multimedia3 {
+ link-name = "MultiMedia3";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA3>;
+ };
+ };
+
+ dai-link-multimedia4 {
+ link-name = "MultiMedia4";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA4>;
+ };
+ };
+
+ dai-link-voicemmode1 {
+ link-name = "VoiceMMode1";
+ cpu {
+ sound-dai = <&q6voicedai VOICEMMODE1>;
+ };
+ };
+
+ sound_dai_primary: dai-link-primary {
+ link-name = "Primary MI2S";
+ cpu {
+ sound-dai = <&q6afedai PRIMARY_MI2S_RX>;
+ };
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ codec {
+ sound-dai = <&lpass_codec 0>, <&wcd_codec 0>;
+ };
+ };
+
+ sound_dai_secondary: dai-link-secondary {
+ link-name = "Secondary MI2S";
+ status = "disabled"; /* Needs extra codec configuration */
+ cpu {
+ sound-dai = <&q6afedai SECONDARY_MI2S_RX>;
+ };
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ };
+
+ sound_dai_tertiary: dai-link-tertiary {
+ link-name = "Tertiary MI2S";
+ cpu {
+ sound-dai = <&q6afedai TERTIARY_MI2S_TX>;
+ };
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ codec {
+ sound-dai = <&lpass_codec 1>, <&wcd_codec 1>;
+ };
+ };
+
+ sound_dai_quaternary: dai-link-quaternary {
+ link-name = "Quaternary MI2S";
+ status = "disabled"; /* Needs extra codec configuration */
+ cpu {
+ sound-dai = <&q6afedai QUATERNARY_MI2S_RX>;
+ };
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ };
+};
+
&usb {
extcon = <&pm8909_charger>;
status = "okay";
@@ -242,6 +377,20 @@
extcon = <&pm8909_charger>;
};
+&wcd_codec {
+ status = "okay";
+
+ qcom,hphl-jack-type-normally-open;
+ qcom,micbias1-ext-cap;
+ qcom,micbias2-ext-cap;
+ qcom,mbhc-vthreshold-low = <85 120 225 450 500>;
+ qcom,mbhc-vthreshold-high = <85 120 225 450 500>;
+
+ vdd-cdc-io-supply = <&pm8909_l5>;
+ vdd-cdc-tx-rx-cx-supply = <&pm8909_s2>;
+ vdd-micbias-supply = <&pm8909_l13>;
+};
+
&wcnss {
status = "okay";
};
From a7af0a9402f776885be06ec1da6f049aa5c860f2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Otto=20Pfl=C3=BCger?= <otto.pflueger@abscue.de>
Date: Tue, 21 Mar 2023 16:06:01 +0100
Subject: [PATCH 09/11] ARM: dts: qcom: msm8909-nokia-leo-common: add sound
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
.../qcom/qcom-msm8909-nokia-leo-common.dtsi | 164 +++++++++++++++++-
1 file changed, 155 insertions(+), 9 deletions(-)
diff --git a/arch/arm/boot/dts/qcom/qcom-msm8909-nokia-leo-common.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8909-nokia-leo-common.dtsi
index 709f4813d41359..f4b63bf83a9524 100644
--- a/arch/arm/boot/dts/qcom/qcom-msm8909-nokia-leo-common.dtsi
+++ b/arch/arm/boot/dts/qcom/qcom-msm8909-nokia-leo-common.dtsi
@@ -122,6 +122,10 @@
};
};
+&apr {
+ status = "okay";
+};
+
&blsp_spi5 {
status = "okay";
@@ -163,15 +167,6 @@
status = "okay";
};
-&sdhc_1 {
- status = "okay";
-};
-
-&sdhc_2 {
- non-removable;
- status = "okay";
-};
-
&pm8909_bms {
monitored-battery = <&bat>;
power-supplies = <&pm8909_charger>;
@@ -198,6 +193,143 @@
status = "okay";
};
+&q6afedai {
+ dai@16 {
+ reg = <PRIMARY_MI2S_RX>;
+ qcom,sd-lines = <0 1>;
+ };
+ dai@20 {
+ reg = <TERTIARY_MI2S_TX>;
+ qcom,sd-lines = <0 1>;
+ };
+};
+
+&q6asmdai {
+ dai@0 {
+ reg = <0>;
+ direction = <Q6ASM_DAI_RX>;
+ };
+ dai@1 {
+ reg = <1>;
+ direction = <Q6ASM_DAI_TX>;
+ };
+ dai@2 {
+ reg = <2>;
+ direction = <Q6ASM_DAI_RX>;
+ };
+ dai@3 {
+ reg = <3>;
+ direction = <Q6ASM_DAI_RX>;
+ is-compress-dai;
+ };
+};
+
+&sdhc_1 {
+ status = "okay";
+};
+
+&sdhc_2 {
+ non-removable;
+ status = "okay";
+};
+
+&sound {
+ status = "okay";
+ model = "msm8916";
+
+ audio-routing =
+ "AMIC1", "MIC BIAS External1",
+ "AMIC2", "MIC BIAS Internal2",
+ "AMIC3", "MIC BIAS External1";
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&cdc_pdm_lines_act>;
+ pinctrl-1 = <&cdc_pdm_lines_sus>;
+
+ dai-link-multimedia1 {
+ link-name = "MultiMedia1";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
+ };
+ };
+
+ dai-link-multimedia2 {
+ link-name = "MultiMedia2";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA2>;
+ };
+ };
+
+ dai-link-multimedia3 {
+ link-name = "MultiMedia3";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA3>;
+ };
+ };
+
+ dai-link-multimedia4 {
+ link-name = "MultiMedia4";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA4>;
+ };
+ };
+
+ dai-link-voicemmode1 {
+ link-name = "VoiceMMode1";
+ cpu {
+ sound-dai = <&q6voicedai VOICEMMODE1>;
+ };
+ };
+
+ sound_dai_primary: dai-link-primary {
+ link-name = "Primary MI2S";
+ cpu {
+ sound-dai = <&q6afedai PRIMARY_MI2S_RX>;
+ };
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ codec {
+ sound-dai = <&lpass_codec 0>, <&wcd_codec 0>;
+ };
+ };
+
+ sound_dai_secondary: dai-link-secondary {
+ link-name = "Secondary MI2S";
+ status = "disabled"; /* Needs extra codec configuration */
+ cpu {
+ sound-dai = <&q6afedai SECONDARY_MI2S_RX>;
+ };
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ };
+
+ sound_dai_tertiary: dai-link-tertiary {
+ link-name = "Tertiary MI2S";
+ cpu {
+ sound-dai = <&q6afedai TERTIARY_MI2S_TX>;
+ };
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ codec {
+ sound-dai = <&lpass_codec 1>, <&wcd_codec 1>;
+ };
+ };
+
+ sound_dai_quaternary: dai-link-quaternary {
+ link-name = "Quaternary MI2S";
+ status = "disabled"; /* Needs extra codec configuration */
+ cpu {
+ sound-dai = <&q6afedai QUATERNARY_MI2S_RX>;
+ };
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ };
+};
+
&usb {
extcon = <&pm8909_charger>;
status = "okay";
@@ -207,6 +339,20 @@
extcon = <&pm8909_charger>;
};
+&wcd_codec {
+ status = "okay";
+
+ qcom,hphl-jack-type-normally-open;
+ qcom,micbias1-ext-cap;
+ qcom,micbias2-ext-cap;
+ qcom,mbhc-vthreshold-low = <75 150 225 450 500>;
+ qcom,mbhc-vthreshold-high = <75 150 225 450 500>;
+
+ vdd-cdc-io-supply = <&pm8909_l5>;
+ vdd-cdc-tx-rx-cx-supply = <&pm8909_s2>;
+ vdd-micbias-supply = <&pm8909_l13>;
+};
+
&wcnss {
status = "okay";
};
From 06de84fe8dd5c8f62292ef215538bd07e5d3fee2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Otto=20Pfl=C3=BCger?= <otto.pflueger@abscue.de>
Date: Thu, 20 Apr 2023 18:45:03 +0200
Subject: [PATCH 10/11] ASoC: qdsp6: q6voice-dai: Add VoiceMMode1 DAI
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
VoiceMMode1 is used instead of CS-Voice on newer firmwares.
Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
---
include/dt-bindings/sound/qcom,q6voice.h | 7 +
sound/soc/qcom/qdsp6/q6mvm.c | 14 ++
sound/soc/qcom/qdsp6/q6voice-dai.c | 184 +++++++++++++++++++----
sound/soc/qcom/qdsp6/q6voice.h | 16 +-
4 files changed, 180 insertions(+), 41 deletions(-)
diff --git a/include/dt-bindings/sound/qcom,q6voice.h b/include/dt-bindings/sound/qcom,q6voice.h
index fe5aa3a3fce49b..0d0a718c55bd40 100644
--- a/include/dt-bindings/sound/qcom,q6voice.h
+++ b/include/dt-bindings/sound/qcom,q6voice.h
@@ -3,5 +3,12 @@
#define __DT_BINDINGS_Q6_VOICE_H__
#define CS_VOICE 0
+#define VOIP 1
+#define VOLTE 1
+#define VOICE2 1
+#define QCHAT 1
+#define VOWLAN 1
+#define VOICEMMODE1 1
+#define VOICEMMODE2 2
#endif /* __DT_BINDINGS_Q6_VOICE_H__ */
diff --git a/sound/soc/qcom/qdsp6/q6mvm.c b/sound/soc/qcom/qdsp6/q6mvm.c
index f1f8d520ba0d9b..ace0d9ca302572 100644
--- a/sound/soc/qcom/qdsp6/q6mvm.c
+++ b/sound/soc/qcom/qdsp6/q6mvm.c
@@ -51,6 +51,20 @@ static inline const char *q6mvm_session_name(enum q6voice_path_type path)
switch (path) {
case Q6VOICE_PATH_VOICE:
return "default modem voice";
+ case Q6VOICE_PATH_VOIP:
+ return "10004000";
+ case Q6VOICE_PATH_VOLTE:
+ return "10C02000";
+ case Q6VOICE_PATH_VOICE2:
+ return "10DC1000";
+ case Q6VOICE_PATH_QCHAT:
+ return "10803000";
+ case Q6VOICE_PATH_VOWLAN:
+ return "10002000";
+ case Q6VOICE_PATH_VOICEMMODE1:
+ return "11C05000";
+ case Q6VOICE_PATH_VOICEMMODE2:
+ return "11DC5000";
default:
return NULL;
}
diff --git a/sound/soc/qcom/qdsp6/q6voice-dai.c b/sound/soc/qcom/qdsp6/q6voice-dai.c
index f3ae9d75f82b7a..356d9ca5b9974a 100644
--- a/sound/soc/qcom/qdsp6/q6voice-dai.c
+++ b/sound/soc/qcom/qdsp6/q6voice-dai.c
@@ -11,20 +11,44 @@
#define DRV_NAME "q6voice-dai"
+static enum q6voice_path_type q6voice_get_path(unsigned int dai_id)
+{
+ switch (dai_id) {
+ case CS_VOICE:
+ return Q6VOICE_PATH_VOICE;
+ case VOICEMMODE1:
+ return Q6VOICE_PATH_VOICEMMODE1;
+ }
+
+ return Q6VOICE_PATH_COUNT;
+}
+
static int q6voice_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct q6voice *v = snd_soc_dai_get_drvdata(dai);
+ enum q6voice_path_type path = q6voice_get_path(dai->driver->id);
- return q6voice_start(v, Q6VOICE_PATH_VOICE, substream->stream);
+ if (path == Q6VOICE_PATH_COUNT) {
+ dev_err(dai->dev, "Invalid DAI ID %u\n", dai->driver->id);
+ return -EINVAL;
+ }
+
+ return q6voice_start(v, path, substream->stream);
}
static void q6voice_dai_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct q6voice *v = snd_soc_dai_get_drvdata(dai);
+ enum q6voice_path_type path = q6voice_get_path(dai->driver->id);
+
+ if (path == Q6VOICE_PATH_COUNT) {
+ dev_err(dai->dev, "Invalid DAI ID %u\n", dai->driver->id);
+ return;
+ }
- q6voice_stop(v, Q6VOICE_PATH_VOICE, substream->stream);
+ q6voice_stop(v, path, substream->stream);
}
static struct snd_soc_dai_ops q6voice_dai_ops = {
@@ -57,6 +81,30 @@ static struct snd_soc_dai_driver q6voice_dais[] = {
},
.ops = &q6voice_dai_ops,
},
+ {
+ .id = VOICEMMODE1,
+ .name = "VOICEMMODE1",
+ /* The constraints here are not really meaningful... */
+ .playback = {
+ .stream_name = "VOICEMMODE1 Playback",
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_8000,
+ .rate_min = 8000,
+ .rate_max = 8000,
+ .channels_min = 1,
+ .channels_max = 1,
+ },
+ .capture = {
+ .stream_name = "VOICEMMODE1 Capture",
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_8000,
+ .rate_min = 8000,
+ .rate_max = 8000,
+ .channels_min = 1,
+ .channels_max = 1,
+ },
+ .ops = &q6voice_dai_ops,
+ },
};
/* FIXME: Use codec2codec instead */
@@ -77,21 +125,26 @@ static int q6voice_dai_open(struct snd_soc_component *component,
return 0;
}
-static int q6voice_get_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int q6voice_get_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol, bool capture)
{
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
struct q6voice *v = snd_soc_component_get_drvdata(c);
- bool capture = !!mc->shift;
+ enum q6voice_path_type path = q6voice_get_path(mc->shift);
+
+ if (path == Q6VOICE_PATH_COUNT) {
+ dev_err(c->dev, "Invalid DAI ID %u\n", mc->shift);
+ return -EINVAL;
+ }
ucontrol->value.integer.value[0] =
- q6voice_get_port(v, Q6VOICE_PATH_VOICE, capture) == mc->reg;
+ q6voice_get_port(v, path, capture) == mc->reg;
return 0;
}
-static int q6voice_put_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int q6voice_put_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol, bool capture)
{
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
@@ -99,61 +152,114 @@ static int q6voice_put_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
(struct soc_mixer_control *)kcontrol->private_value;
struct q6voice *v = snd_soc_component_get_drvdata(c);
bool val = !!ucontrol->value.integer.value[0];
- bool capture = !!mc->shift;
+ enum q6voice_path_type path = q6voice_get_path(mc->shift);
+
+ if (path == Q6VOICE_PATH_COUNT) {
+ dev_err(c->dev, "Invalid DAI ID %u\n", mc->shift);
+ return -EINVAL;
+ }
if (val)
- q6voice_set_port(v, Q6VOICE_PATH_VOICE, capture, mc->reg);
- else if (q6voice_get_port(v, Q6VOICE_PATH_VOICE, capture) == mc->reg)
- q6voice_set_port(v, Q6VOICE_PATH_VOICE, capture, 0);
+ q6voice_set_port(v, path, capture, mc->reg);
+ else if (q6voice_get_port(v, path, capture) == mc->reg)
+ q6voice_set_port(v, path, capture, 0);
snd_soc_dapm_mixer_update_power(dapm, kcontrol, val, NULL);
return 1;
}
-static const struct snd_kcontrol_new voice_tx_mixer_controls[] = {
- SOC_SINGLE_EXT("PRI_MI2S_TX", PRIMARY_MI2S_TX, 1, 1, 0,
- q6voice_get_mixer, q6voice_put_mixer),
- SOC_SINGLE_EXT("SEC_MI2S_TX", SECONDARY_MI2S_TX, 1, 1, 0,
- q6voice_get_mixer, q6voice_put_mixer),
- SOC_SINGLE_EXT("TERT_MI2S_TX", TERTIARY_MI2S_TX, 1, 1, 0,
- q6voice_get_mixer, q6voice_put_mixer),
- SOC_SINGLE_EXT("QUAT_MI2S_TX", QUATERNARY_MI2S_TX, 1, 1, 0,
- q6voice_get_mixer, q6voice_put_mixer),
- SOC_SINGLE_EXT("QUIN_MI2S_TX", QUINARY_MI2S_TX, 1, 1, 0,
- q6voice_get_mixer, q6voice_put_mixer),
+static int q6voice_get_mixer_capture(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+ return q6voice_get_mixer(kcontrol, ucontrol, true);
+}
+
+static int q6voice_get_mixer_playback(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+ return q6voice_get_mixer(kcontrol, ucontrol, false);
+}
+
+static int q6voice_put_mixer_capture(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+ return q6voice_put_mixer(kcontrol, ucontrol, true);
+}
+
+static int q6voice_put_mixer_playback(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+ return q6voice_put_mixer(kcontrol, ucontrol, false);
+}
+
+static const struct snd_kcontrol_new cs_voice_tx_mixer_controls[] = {
+ SOC_SINGLE_EXT("PRI_MI2S_TX", PRIMARY_MI2S_TX, CS_VOICE, 1, 0,
+ q6voice_get_mixer_capture, q6voice_put_mixer_capture),
+ SOC_SINGLE_EXT("SEC_MI2S_TX", SECONDARY_MI2S_TX, CS_VOICE, 1, 0,
+ q6voice_get_mixer_capture, q6voice_put_mixer_capture),
+ SOC_SINGLE_EXT("TERT_MI2S_TX", TERTIARY_MI2S_TX, CS_VOICE, 1, 0,
+ q6voice_get_mixer_capture, q6voice_put_mixer_capture),
+ SOC_SINGLE_EXT("QUAT_MI2S_TX", QUATERNARY_MI2S_TX, CS_VOICE, 1, 0,
+ q6voice_get_mixer_capture, q6voice_put_mixer_capture),
+ SOC_SINGLE_EXT("QUIN_MI2S_TX", QUINARY_MI2S_TX, CS_VOICE, 1, 0,
+ q6voice_get_mixer_capture, q6voice_put_mixer_capture),
+};
+
+static const struct snd_kcontrol_new voicemmode1_tx_mixer_controls[] = {
+ SOC_SINGLE_EXT("PRI_MI2S_TX", PRIMARY_MI2S_TX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer_capture, q6voice_put_mixer_capture),
+ SOC_SINGLE_EXT("SEC_MI2S_TX", SECONDARY_MI2S_TX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer_capture, q6voice_put_mixer_capture),
+ SOC_SINGLE_EXT("TERT_MI2S_TX", TERTIARY_MI2S_TX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer_capture, q6voice_put_mixer_capture),
+ SOC_SINGLE_EXT("QUAT_MI2S_TX", QUATERNARY_MI2S_TX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer_capture, q6voice_put_mixer_capture),
+ SOC_SINGLE_EXT("QUIN_MI2S_TX", QUINARY_MI2S_TX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer_capture, q6voice_put_mixer_capture),
};
static const struct snd_kcontrol_new primary_mi2s_rx_mixer_controls[] = {
- SOC_SINGLE_EXT("CS-Voice", PRIMARY_MI2S_RX, 0, 1, 0,
- q6voice_get_mixer, q6voice_put_mixer)
+ SOC_SINGLE_EXT("CS-Voice", PRIMARY_MI2S_RX, CS_VOICE, 1, 0,
+ q6voice_get_mixer_playback, q6voice_put_mixer_playback),
+ SOC_SINGLE_EXT("VoiceMMode1", PRIMARY_MI2S_RX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer_playback, q6voice_put_mixer_playback),
};
static const struct snd_kcontrol_new secondary_mi2s_rx_mixer_controls[] = {
- SOC_SINGLE_EXT("CS-Voice", SECONDARY_MI2S_RX, 0, 1, 0,
- q6voice_get_mixer, q6voice_put_mixer)
+ SOC_SINGLE_EXT("CS-Voice", SECONDARY_MI2S_RX, CS_VOICE, 1, 0,
+ q6voice_get_mixer_playback, q6voice_put_mixer_playback),
+ SOC_SINGLE_EXT("VoiceMMode1", SECONDARY_MI2S_RX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer_playback, q6voice_put_mixer_playback),
};
static const struct snd_kcontrol_new tertiary_mi2s_rx_mixer_controls[] = {
- SOC_SINGLE_EXT("CS-Voice", TERTIARY_MI2S_RX, 0, 1, 0,
- q6voice_get_mixer, q6voice_put_mixer)
+ SOC_SINGLE_EXT("CS-Voice", TERTIARY_MI2S_RX, CS_VOICE, 1, 0,
+ q6voice_get_mixer_playback, q6voice_put_mixer_playback),
+ SOC_SINGLE_EXT("VoiceMMode1", TERTIARY_MI2S_RX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer_playback, q6voice_put_mixer_playback),
};
static const struct snd_kcontrol_new quaternary_mi2s_rx_mixer_controls[] = {
- SOC_SINGLE_EXT("CS-Voice", QUATERNARY_MI2S_RX, 0, 1, 0,
- q6voice_get_mixer, q6voice_put_mixer)
+ SOC_SINGLE_EXT("CS-Voice", QUATERNARY_MI2S_RX, CS_VOICE, 1, 0,
+ q6voice_get_mixer_playback, q6voice_put_mixer_playback),
+ SOC_SINGLE_EXT("VoiceMMode1", QUATERNARY_MI2S_RX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer_playback, q6voice_put_mixer_playback),
};
static const struct snd_kcontrol_new quinary_mi2s_rx_mixer_controls[] = {
- SOC_SINGLE_EXT("CS-Voice", QUINARY_MI2S_RX, 0, 1, 0,
- q6voice_get_mixer, q6voice_put_mixer)
+ SOC_SINGLE_EXT("CS-Voice", QUINARY_MI2S_RX, CS_VOICE, 1, 0,
+ q6voice_get_mixer_playback, q6voice_put_mixer_playback),
+ SOC_SINGLE_EXT("VoiceMMode1", QUINARY_MI2S_RX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer_playback, q6voice_put_mixer_playback),
};
static const struct snd_soc_dapm_widget q6voice_dapm_widgets[] = {
SND_SOC_DAPM_AIF_IN("CS-VOICE_DL1", "CS-VOICE Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_MIXER("CS-Voice Capture Mixer", SND_SOC_NOPM, 0, 0,
- voice_tx_mixer_controls,
- ARRAY_SIZE(voice_tx_mixer_controls)),
+ cs_voice_tx_mixer_controls,
+ ARRAY_SIZE(cs_voice_tx_mixer_controls)),
+ SND_SOC_DAPM_AIF_IN("VOICEMMODE1_DL1", "VOICEMMODE1 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("VOICEMMODE1_UL1", "VOICEMMODE1 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_MIXER("VoiceMMode1 Capture Mixer", SND_SOC_NOPM, 0, 0,
+ voicemmode1_tx_mixer_controls,
+ ARRAY_SIZE(voicemmode1_tx_mixer_controls)),
SND_SOC_DAPM_MIXER("PRI_MI2S_RX Voice Mixer", SND_SOC_NOPM, 0, 0,
primary_mi2s_rx_mixer_controls,
ARRAY_SIZE(primary_mi2s_rx_mixer_controls)),
@@ -178,12 +284,24 @@ static const struct snd_soc_dapm_route q6voice_dapm_routes[] = {
{ "CS-Voice Capture Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX" },
{ "CS-Voice Capture Mixer", "QUIN_MI2S_TX", "QUIN_MI2S_TX" },
{ "CS-VOICE_UL1", NULL, "CS-Voice Capture Mixer" },
+ { "VoiceMMode1 Capture Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX" },
+ { "VoiceMMode1 Capture Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX" },
+ { "VoiceMMode1 Capture Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX" },
+ { "VoiceMMode1 Capture Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX" },
+ { "VoiceMMode1 Capture Mixer", "QUIN_MI2S_TX", "QUIN_MI2S_TX" },
+ { "VOICEMMODE1_UL1", NULL, "VoiceMMode1 Capture Mixer" },
{ "PRI_MI2S_RX Voice Mixer", "CS-Voice", "CS-VOICE_DL1" },
{ "SEC_MI2S_RX Voice Mixer", "CS-Voice", "CS-VOICE_DL1" },
{ "TERT_MI2S_RX Voice Mixer", "CS-Voice", "CS-VOICE_DL1" },
{ "QUAT_MI2S_RX Voice Mixer", "CS-Voice", "CS-VOICE_DL1" },
{ "QUIN_MI2S_RX Voice Mixer", "CS-Voice", "CS-VOICE_DL1" },
+ { "PRI_MI2S_RX Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL1" },
+ { "SEC_MI2S_RX Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL1" },
+ { "TERT_MI2S_RX Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL1" },
+ { "QUAT_MI2S_RX Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL1" },
+ { "QUIN_MI2S_RX Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL1" },
+
{ "PRI_MI2S_RX", NULL, "PRI_MI2S_RX Voice Mixer" },
{ "SEC_MI2S_RX", NULL, "SEC_MI2S_RX Voice Mixer" },
{ "TERT_MI2S_RX", NULL, "TERT_MI2S_RX Voice Mixer" },
diff --git a/sound/soc/qcom/qdsp6/q6voice.h b/sound/soc/qcom/qdsp6/q6voice.h
index 5b2d2dd679b34d..13b058c7303ac9 100644
--- a/sound/soc/qcom/qdsp6/q6voice.h
+++ b/sound/soc/qcom/qdsp6/q6voice.h
@@ -3,14 +3,14 @@
#define _Q6_VOICE_H
enum q6voice_path_type {
- Q6VOICE_PATH_VOICE = 0,
- /* TODO: Q6VOICE_PATH_VOIP = 1, */
- /* TODO: Q6VOICE_PATH_VOLTE = 2, */
- /* TODO: Q6VOICE_PATH_VOICE2 = 3, */
- /* TODO: Q6VOICE_PATH_QCHAT = 4, */
- /* TODO: Q6VOICE_PATH_VOWLAN = 5, */
- /* TODO: Q6VOICE_PATH_VOICEMMODE1 = 6, */
- /* TODO: Q6VOICE_PATH_VOICEMMODE2 = 7, */
+ Q6VOICE_PATH_VOICE = 0,
+ Q6VOICE_PATH_VOIP = 1,
+ Q6VOICE_PATH_VOLTE = 2,
+ Q6VOICE_PATH_VOICE2 = 3,
+ Q6VOICE_PATH_QCHAT = 4,
+ Q6VOICE_PATH_VOWLAN = 5,
+ Q6VOICE_PATH_VOICEMMODE1 = 6,
+ Q6VOICE_PATH_VOICEMMODE2 = 7,
Q6VOICE_PATH_COUNT
};
From 878528f878a0ba52d3f972a600e7da05b6532540 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Otto=20Pfl=C3=BCger?= <otto.pflueger@abscue.de>
Date: Tue, 12 Dec 2023 14:29:48 +0100
Subject: [PATCH 11/11] fixup! ASoC: qcom: q6afe: provide fallback for digital
codec clock
---
sound/soc/qcom/qdsp6/q6afe.c | 55 +++++++++++++++++++-----------------
1 file changed, 29 insertions(+), 26 deletions(-)
diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c
index 7b5d90e1452932..82b54abe519081 100644
--- a/sound/soc/qcom/qdsp6/q6afe.c
+++ b/sound/soc/qcom/qdsp6/q6afe.c
@@ -1123,14 +1123,14 @@ static int q6afe_port_set_param(struct q6afe_port *port, void *data,
psize, port->token);
}
-static int q6afe_port_set_param_v2(struct q6afe_port *port, void *data,
- int param_id, int module_id, int psize)
+static int q6afe_set_param_v2(struct q6afe *afe, struct q6afe_port *port,
+ void *data, int param_id, int module_id, int psize,
+ int token)
{
struct afe_port_cmd_set_param_v2 *param;
struct afe_port_param_data_v2 *pdata;
- struct q6afe *afe = port->afe;
struct apr_pkt *pkt;
- u16 port_id = port->id;
+ u16 port_id = port ? port->id : 0;
int ret, pkt_size;
void *p, *pl;
@@ -1151,7 +1151,7 @@ static int q6afe_port_set_param_v2(struct q6afe_port *port, void *data,
pkt->hdr.pkt_size = pkt_size;
pkt->hdr.src_port = 0;
pkt->hdr.dest_port = 0;
- pkt->hdr.token = port->token;
+ pkt->hdr.token = token;
pkt->hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
param->port_id = port_id;
@@ -1172,6 +1172,13 @@ static int q6afe_port_set_param_v2(struct q6afe_port *port, void *data,
return ret;
}
+static int q6afe_port_set_param_v2(struct q6afe_port *port, void *data,
+ int param_id, int module_id, int psize)
+{
+ return q6afe_set_param_v2(port->afe, port, data, param_id, module_id,
+ psize, port->token);
+}
+
static int q6afe_port_set_lpass_clock(struct q6afe_port *port,
struct afe_clk_cfg *cfg)
{
@@ -1203,30 +1210,26 @@ int q6afe_set_lpass_clock(struct device *dev, int clk_id, int attri,
struct q6afe *afe = dev_get_drvdata(dev->parent);
struct afe_clk_set cset = {0,};
- /*
- * v2 clocks specified in the device tree may not be supported by the
- * firmware. If this is the digital codec core clock, fall back to the
- * old method for setting it.
- */
if (q6core_get_adsp_version() < Q6_ADSP_VERSION_2_7) {
- struct q6afe_port *port;
struct afe_digital_clk_cfg dcfg = {0,};
- int ret;
- if (clk_id != Q6AFE_LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE)
- return -EINVAL;
-
- port = q6afe_port_get_from_id(dev, PRIMARY_MI2S_RX);
- if (IS_ERR(port))
- return PTR_ERR(port);
-
- dcfg.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG;
- dcfg.clk_val = freq;
- dcfg.clk_root = 5;
- ret = q6afe_set_digital_codec_core_clock(port, &dcfg);
-
- q6afe_port_put(port);
- return ret;
+ switch (clk_id) {
+ /*
+ * DSP firmware versions below 2.7 do not support configuring internal
+ * digital codec core clk using AFE_PARAM_ID_CLOCK_SET
+ */
+ case Q6AFE_LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE:
+ dcfg.i2s_cfg_minor_version = AFE_API_VERSION_I2S_CONFIG;
+ dcfg.clk_val = freq;
+ dcfg.clk_root = 5;
+ return q6afe_set_param_v2(afe, NULL, &dcfg,
+ AFE_PARAM_ID_INT_DIGITAL_CDC_CLK_CONFIG,
+ AFE_MODULE_AUDIO_DEV_INTERFACE,
+ sizeof(dcfg),
+ AFE_CLK_TOKEN);
+ default:
+ break;
+ }
}
cset.clk_set_minor_version = AFE_API_VERSION_CLOCK_SET;