[PATCH v3 0/8] MSM8953/MSM8976 ASoC support
Introduce support for basic sound card setup on MSM8953/MSM8976 platforms, document new compatibles and introduce support for more dais. Most of code is sourced from msm8953-mainline fork over github with some changes implemented by me,some basic changes are mentioned in each patch.
Changes since v2 =============== 1. Guarded ioremap on quinary mux with checking if resource is not NULL 2. Introduced compatible based reg overriding in wcd-analog driver 3. Separated PM8950/PM8953 codec patches 4. Moved reg/reg-names back into top-level and rewrote as in comments 5. Separated MSM8953/MSM8976 QDSP6 patches 6. Added Lineout patch
[1] - https://lore.kernel.org/lkml/20240723083300.35605-1-krzysztof.kozlowski@lina...
Changes since v1 ================ 1. Rebased dt-bindings documentation based on Krzysztof's split patch[1] 2. Resolved clang errors by guarding ret verification inside if 3. Switched quin-iomux to devm_ioremap_resource to not fail on msm8916
Signed-off-by: Adam Skladowski a39.skl@gmail.com --- Adam Skladowski (4): ASoC: dt-bindings: pm8916-wcd-analog-codec: Document pm8950/pm8953 ASoC: msm8916-wcd-analog: add pm8950 codec ASoC: dt-bindings: apq8016-sbc: Add msm8953/msm8976-qdsp6-sndcard ASoC: qcom: apq8016_sbc: Add support for msm8976 SoC
Vladimir Lypak (4): ASoC: qcom: apq8016_sbc.c: Add Quinary support ASoC: msm8916-wcd-analog: add pm8953 codec ASoC: qcom: apq8016_sbc: Add support for msm8953 SoC ASoC: msm8916-wcd-analog: add lineout output
.../bindings/sound/qcom,apq8016-sbc-sndcard.yaml | 27 ++++ .../sound/qcom,pm8916-wcd-analog-codec.yaml | 6 +- sound/soc/codecs/msm8916-wcd-analog.c | 145 ++++++++++++++++++++- sound/soc/qcom/apq8016_sbc.c | 88 ++++++++++++- 4 files changed, 257 insertions(+), 9 deletions(-) --- base-commit: 31c2a5c4bf3673b0bf098f358ea931b9ada1e7de change-id: 20240729-msm8953-msm8976-asoc-65f973a13165
Best regards,
From: Vladimir Lypak vladimir.lypak@gmail.com
Add support for configuring Quinary Mi2S interface it will be used on MSM8953 and MSM8976 platform.
Signed-off-by: Vladimir Lypak vladimir.lypak@gmail.com [Adam: Split from MSM8953 support patch,add msg] Signed-off-by: Adam Skladowski a39.skl@gmail.com --- sound/soc/qcom/apq8016_sbc.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 3023cf180a75..5a29adbd3f82 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -20,12 +20,13 @@ #include "common.h" #include "qdsp6/q6afe.h"
-#define MI2S_COUNT (MI2S_QUATERNARY + 1) +#define MI2S_COUNT (MI2S_QUINARY + 1)
struct apq8016_sbc_data { struct snd_soc_card card; void __iomem *mic_iomux; void __iomem *spkr_iomux; + void __iomem *quin_iomux; struct snd_soc_jack jack; bool jack_setup; int mi2s_clk_count[MI2S_COUNT]; @@ -86,6 +87,12 @@ static int apq8016_dai_init(struct snd_soc_pcm_runtime *rtd, int mi2s) SPKR_CTL_TLMM_DATA1_EN | SPKR_CTL_TLMM_WS_OUT_SEL_SEC | SPKR_CTL_TLMM_WS_EN_SEL_SEC, pdata->spkr_iomux); break; + case MI2S_QUINARY: + /* Configure Quinary MI2S */ + if (!pdata->quin_iomux) + return -ENOENT; + writel(readl(pdata->quin_iomux) | 0x01, pdata->quin_iomux); + break; case MI2S_TERTIARY: writel(readl(pdata->mic_iomux) | MIC_CTRL_TER_WS_SLAVE_SEL | MIC_CTRL_TLMM_SCLK_EN, @@ -177,6 +184,9 @@ static int qdsp6_dai_get_lpass_id(struct snd_soc_dai *cpu_dai) case QUATERNARY_MI2S_RX: case QUATERNARY_MI2S_TX: return MI2S_QUATERNARY; + case QUINARY_MI2S_RX: + case QUINARY_MI2S_TX: + return MI2S_QUINARY; default: return -EINVAL; } @@ -290,6 +300,7 @@ static int apq8016_sbc_platform_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct snd_soc_card *card; struct apq8016_sbc_data *data; + struct resource *res; int ret;
add_ops = device_get_match_data(&pdev->dev); @@ -320,6 +331,10 @@ static int apq8016_sbc_platform_probe(struct platform_device *pdev) if (IS_ERR(data->spkr_iomux)) return PTR_ERR(data->spkr_iomux);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "quin-iomux"); + if (res != NULL) + data->quin_iomux = devm_ioremap_resource(&pdev->dev, res); + snd_soc_card_set_drvdata(card, data);
add_ops(card);
On Wed, Jul 31, 2024 at 05:25:25PM GMT, Adam Skladowski wrote:
From: Vladimir Lypak vladimir.lypak@gmail.com
Add support for configuring Quinary Mi2S interface it will be used on MSM8953 and MSM8976 platform.
Signed-off-by: Vladimir Lypak vladimir.lypak@gmail.com [Adam: Split from MSM8953 support patch,add msg] Signed-off-by: Adam Skladowski a39.skl@gmail.com
sound/soc/qcom/apq8016_sbc.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org
On 31.07.2024 5:25 PM, Adam Skladowski wrote:
From: Vladimir Lypak vladimir.lypak@gmail.com
Add support for configuring Quinary Mi2S interface it will be used on MSM8953 and MSM8976 platform.
Signed-off-by: Vladimir Lypak vladimir.lypak@gmail.com [Adam: Split from MSM8953 support patch,add msg] Signed-off-by: Adam Skladowski a39.skl@gmail.com
sound/soc/qcom/apq8016_sbc.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 3023cf180a75..5a29adbd3f82 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -20,12 +20,13 @@ #include "common.h" #include "qdsp6/q6afe.h"
-#define MI2S_COUNT (MI2S_QUATERNARY + 1) +#define MI2S_COUNT (MI2S_QUINARY + 1)
struct apq8016_sbc_data { struct snd_soc_card card; void __iomem *mic_iomux; void __iomem *spkr_iomux;
- void __iomem *quin_iomux; struct snd_soc_jack jack; bool jack_setup; int mi2s_clk_count[MI2S_COUNT];
@@ -86,6 +87,12 @@ static int apq8016_dai_init(struct snd_soc_pcm_runtime *rtd, int mi2s) SPKR_CTL_TLMM_DATA1_EN | SPKR_CTL_TLMM_WS_OUT_SEL_SEC | SPKR_CTL_TLMM_WS_EN_SEL_SEC, pdata->spkr_iomux); break;
- case MI2S_QUINARY:
/* Configure Quinary MI2S */
if (!pdata->quin_iomux)
return -ENOENT;
writel(readl(pdata->quin_iomux) | 0x01, pdata->quin_iomux);
I'm nitpicking, but 0x01 here is BIT(0)
Acked-by: Konrad Dybcio konradybcio@kernel.org
Konrad
Document pm8950 and pm8953 analog audio codecs.
Signed-off-by: Adam Skladowski a39.skl@gmail.com --- .../devicetree/bindings/sound/qcom,pm8916-wcd-analog-codec.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/qcom,pm8916-wcd-analog-codec.yaml b/Documentation/devicetree/bindings/sound/qcom,pm8916-wcd-analog-codec.yaml index 94e7a1860977..8af8bb747abe 100644 --- a/Documentation/devicetree/bindings/sound/qcom,pm8916-wcd-analog-codec.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,pm8916-wcd-analog-codec.yaml @@ -14,8 +14,10 @@ description:
properties: compatible: - const: qcom,pm8916-wcd-analog-codec - + enum: + - qcom,pm8916-wcd-analog-codec + - qcom,pm8950-wcd-analog-codec + - qcom,pm8953-wcd-analog-codec reg: maxItems: 1
On 31/07/2024 17:25, Adam Skladowski wrote:
Document pm8950 and pm8953 analog audio codecs.
Signed-off-by: Adam Skladowski a39.skl@gmail.com
.../devicetree/bindings/sound/qcom,pm8916-wcd-analog-codec.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/qcom,pm8916-wcd-analog-codec.yaml b/Documentation/devicetree/bindings/sound/qcom,pm8916-wcd-analog-codec.yaml index 94e7a1860977..8af8bb747abe 100644 --- a/Documentation/devicetree/bindings/sound/qcom,pm8916-wcd-analog-codec.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,pm8916-wcd-analog-codec.yaml @@ -14,8 +14,10 @@ description:
properties: compatible:
- const: qcom,pm8916-wcd-analog-codec
- enum:
- qcom,pm8916-wcd-analog-codec
- qcom,pm8950-wcd-analog-codec
- qcom,pm8953-wcd-analog-codec
Why dropping new line?
Best regards, Krzysztof
Add regs overrides for PM8950 codec and implement matching reg overrides via compatible.
Signed-off-by: Adam Skladowski a39.skl@gmail.com --- sound/soc/codecs/msm8916-wcd-analog.c | 52 ++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 4 deletions(-)
diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c index 9ca381812975..13df60409857 100644 --- a/sound/soc/codecs/msm8916-wcd-analog.c +++ b/sound/soc/codecs/msm8916-wcd-analog.c @@ -232,6 +232,8 @@ #define RX_EAR_CTL_PA_SEL_MASK BIT(7) #define RX_EAR_CTL_PA_SEL BIT(7)
+#define CDC_A_RX_EAR_STATUS (0xf1A1) + #define CDC_A_SPKR_DAC_CTL (0xf1B0) #define SPKR_DAC_CTL_DAC_RESET_MASK BIT(4) #define SPKR_DAC_CTL_DAC_RESET_NORMAL 0 @@ -250,6 +252,7 @@ SPKR_DRV_CAL_EN | SPKR_DRV_SETTLE_EN | \ SPKR_DRV_FW_EN | SPKR_DRV_BOOST_SET | \ SPKR_DRV_CMFB_SET | SPKR_DRV_GAIN_SET) +#define CDC_A_SPKR_ANA_BIAS_SET (0xf1B3) #define CDC_A_SPKR_OCP_CTL (0xf1B4) #define CDC_A_SPKR_PWRSTG_CTL (0xf1B5) #define SPKR_PWRSTG_CTL_DAC_EN_MASK BIT(0) @@ -264,6 +267,7 @@
#define CDC_A_SPKR_DRV_DBG (0xf1B7) #define CDC_A_CURRENT_LIMIT (0xf1C0) +#define CDC_A_BYPASS_MODE (0xf1C2) #define CDC_A_BOOST_EN_CTL (0xf1C3) #define CDC_A_SLOPE_COMP_IP_ZERO (0xf1C4) #define CDC_A_SEC_ACCESS (0xf1D0) @@ -286,6 +290,11 @@ static const char * const supply_names[] = {
#define MBHC_MAX_BUTTONS (5)
+struct wcd_reg_seq { + const struct reg_default *seq; + int seq_size; +}; + struct pm8916_wcd_analog_priv { u16 pmic_rev; u16 codec_version; @@ -715,9 +724,41 @@ static const struct reg_default wcd_reg_defaults_2_0[] = { {CDC_A_MASTER_BIAS_CTL, 0x30}, };
+static const struct wcd_reg_seq pm8916_data = { + .seq = wcd_reg_defaults_2_0, + .seq_size = ARRAY_SIZE(wcd_reg_defaults_2_0), +}; + +static const struct reg_default wcd_reg_defaults_pm8950[] = { + {CDC_A_RX_COM_OCP_CTL, 0xd1}, + {CDC_A_RX_COM_OCP_COUNT, 0xff}, + {CDC_D_SEC_ACCESS, 0xa5}, + {CDC_D_PERPH_RESET_CTL3, 0x0f}, + {CDC_A_TX_1_2_OPAMP_BIAS, 0x4c}, + {CDC_A_NCP_FBCTRL, 0xa8}, + {CDC_A_NCP_VCTRL, 0xa4}, + {CDC_A_SPKR_DRV_CTL, 0x69}, + {CDC_A_SPKR_DRV_DBG, 0x01}, + {CDC_A_SEC_ACCESS, 0xa5}, + {CDC_A_PERPH_RESET_CTL3, 0x0f}, + {CDC_A_CURRENT_LIMIT, 0x82}, + {CDC_A_SPKR_ANA_BIAS_SET, 0x41}, + {CDC_A_SPKR_DAC_CTL, 0x03}, + {CDC_A_SPKR_OCP_CTL, 0xe1}, + {CDC_A_RX_HPH_BIAS_PA, 0xfa}, + {CDC_A_MASTER_BIAS_CTL, 0x30}, + {CDC_A_MICB_1_INT_RBIAS, 0x00}, +}; + +static const struct wcd_reg_seq pm8950_data = { + .seq = wcd_reg_defaults_pm8950, + .seq_size = ARRAY_SIZE(wcd_reg_defaults_pm8950), +}; + static int pm8916_wcd_analog_probe(struct snd_soc_component *component) { struct pm8916_wcd_analog_priv *priv = dev_get_drvdata(component->dev); + const struct wcd_reg_seq *wcd_reg_init_data; int err, reg;
err = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies); @@ -738,9 +779,11 @@ static int pm8916_wcd_analog_probe(struct snd_soc_component *component) snd_soc_component_write(component, CDC_D_PERPH_RESET_CTL4, 0x01); snd_soc_component_write(component, CDC_A_PERPH_RESET_CTL4, 0x01);
- for (reg = 0; reg < ARRAY_SIZE(wcd_reg_defaults_2_0); reg++) - snd_soc_component_write(component, wcd_reg_defaults_2_0[reg].reg, - wcd_reg_defaults_2_0[reg].def); + wcd_reg_init_data = of_device_get_match_data(component->dev); + + for (reg = 0; reg < wcd_reg_init_data->seq_size; reg++) + snd_soc_component_write(component, wcd_reg_init_data->seq[reg].reg, + wcd_reg_init_data->seq[reg].def);
priv->component = component;
@@ -1259,7 +1302,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev) }
static const struct of_device_id pm8916_wcd_analog_spmi_match_table[] = { - { .compatible = "qcom,pm8916-wcd-analog-codec", }, + { .compatible = "qcom,pm8916-wcd-analog-codec", .data = &pm8916_data }, + { .compatible = "qcom,pm8950-wcd-analog-codec", .data = &pm8950_data }, { } };
On Wed, Jul 31, 2024 at 05:25:27PM GMT, Adam Skladowski wrote:
Add regs overrides for PM8950 codec and implement matching reg overrides via compatible.
Signed-off-by: Adam Skladowski a39.skl@gmail.com
sound/soc/codecs/msm8916-wcd-analog.c | 52 ++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 4 deletions(-)
Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org
From: Vladimir Lypak vladimir.lypak@gmail.com
Add regs overrides for PM8953 codec.
Signed-off-by: Vladimir Lypak vladimir.lypak@gmail.com [Adam: rename codec] Signed-off-by: Adam Skladowski a39.skl@gmail.com --- sound/soc/codecs/msm8916-wcd-analog.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c index 13df60409857..b9325290c28d 100644 --- a/sound/soc/codecs/msm8916-wcd-analog.c +++ b/sound/soc/codecs/msm8916-wcd-analog.c @@ -755,6 +755,34 @@ static const struct wcd_reg_seq pm8950_data = { .seq_size = ARRAY_SIZE(wcd_reg_defaults_pm8950), };
+static const struct reg_default wcd_reg_defaults_pm8953[] = { + {CDC_A_RX_COM_OCP_CTL, 0xd1}, + {CDC_A_RX_COM_OCP_COUNT, 0xff}, + {CDC_D_SEC_ACCESS, 0xa5}, + {CDC_D_PERPH_RESET_CTL3, 0x0f}, + {CDC_A_TX_1_2_OPAMP_BIAS, 0x4c}, + {CDC_A_NCP_FBCTRL, 0xa8}, + {CDC_A_NCP_VCTRL, 0xa4}, + {CDC_A_SPKR_DRV_CTL, 0x69}, + {CDC_A_SPKR_DRV_DBG, 0x01}, + {CDC_A_SEC_ACCESS, 0xa5}, + {CDC_A_PERPH_RESET_CTL3, 0x0f}, + {CDC_A_CURRENT_LIMIT, 0xa2}, + {CDC_A_BYPASS_MODE, 0x18}, + {CDC_A_SPKR_ANA_BIAS_SET, 0x41}, + {CDC_A_SPKR_DAC_CTL, 0x03}, + {CDC_A_SPKR_OCP_CTL, 0xe1}, + {CDC_A_RX_HPH_BIAS_PA, 0xfa}, + {CDC_A_RX_EAR_STATUS, 0x10}, + {CDC_A_MASTER_BIAS_CTL, 0x30}, + {CDC_A_MICB_1_INT_RBIAS, 0x00}, +}; + +static const struct wcd_reg_seq pm8953_data = { + .seq = wcd_reg_defaults_pm8953, + .seq_size = ARRAY_SIZE(wcd_reg_defaults_pm8953), +}; + static int pm8916_wcd_analog_probe(struct snd_soc_component *component) { struct pm8916_wcd_analog_priv *priv = dev_get_drvdata(component->dev); @@ -1304,6 +1332,7 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev) static const struct of_device_id pm8916_wcd_analog_spmi_match_table[] = { { .compatible = "qcom,pm8916-wcd-analog-codec", .data = &pm8916_data }, { .compatible = "qcom,pm8950-wcd-analog-codec", .data = &pm8950_data }, + { .compatible = "qcom,pm8953-wcd-analog-codec", .data = &pm8953_data }, { } };
On Wed, Jul 31, 2024 at 05:25:28PM GMT, Adam Skladowski wrote:
From: Vladimir Lypak vladimir.lypak@gmail.com
Add regs overrides for PM8953 codec.
Signed-off-by: Vladimir Lypak vladimir.lypak@gmail.com [Adam: rename codec] Signed-off-by: Adam Skladowski a39.skl@gmail.com
sound/soc/codecs/msm8916-wcd-analog.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org
Document MSM8953/MSM8976 QDSP6 cards.
Signed-off-by: Adam Skladowski a39.skl@gmail.com --- .../bindings/sound/qcom,apq8016-sbc-sndcard.yaml | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc-sndcard.yaml b/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc-sndcard.yaml index 6ad451549036..43db5ad65d75 100644 --- a/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc-sndcard.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc-sndcard.yaml @@ -15,16 +15,22 @@ properties: enum: - qcom,apq8016-sbc-sndcard - qcom,msm8916-qdsp6-sndcard + - qcom,msm8953-qdsp6-sndcard + - qcom,msm8976-qdsp6-sndcard
reg: + minItems: 2 items: - description: Microphone I/O mux register address - description: Speaker I/O mux register address + - description: Quinary Mi2S I/O mux register address
reg-names: + minItems: 2 items: - const: mic-iomux - const: spkr-iomux + - const: quin-iomux
audio-routing: $ref: /schemas/types.yaml#/definitions/non-unique-string-array @@ -106,6 +112,27 @@ required: - reg-names - model
+allOf: + - if: + properties: + compatible: + contains: + enum: + - qcom,apq8016-sbc-sndcard + - qcom,msm8916-qdsp6-sndcard + then: + properties: + reg: + maxItems: 2 + reg-names: + maxItems: 2 + else: + properties: + reg: + minItems: 3 + reg-names: + minItems: 3 + additionalProperties: false
examples:
On 31/07/2024 17:25, Adam Skladowski wrote:
Document MSM8953/MSM8976 QDSP6 cards.
Signed-off-by: Adam Skladowski a39.skl@gmail.com
Reviewed-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org
Best regards, Krzysztof
From: Vladimir Lypak vladimir.lypak@gmail.com
Introduce support for audio card on MSM8953 platform. Main difference between MSM8953 and MSM8916 is Q6AFE CLK API supported by firmware which influence way we set codec clocks. SoCs shipping on at least msm-3.18 should use v2 clocks.
Signed-off-by: Vladimir Lypak vladimir.lypak@gmail.com [Adam: rename functions, add msg] Co-developed-by: Adam Skladowski a39.skl@gmail.com Signed-off-by: Adam Skladowski a39.skl@gmail.com --- sound/soc/qcom/apq8016_sbc.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-)
diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 5a29adbd3f82..3ed35beb671a 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -22,6 +22,11 @@
#define MI2S_COUNT (MI2S_QUINARY + 1)
+enum afe_clk_api { + Q6AFE_CLK_V1, + Q6AFE_CLK_V2 +}; + struct apq8016_sbc_data { struct snd_soc_card card; void __iomem *mic_iomux; @@ -29,6 +34,7 @@ struct apq8016_sbc_data { void __iomem *quin_iomux; struct snd_soc_jack jack; bool jack_setup; + enum afe_clk_api q6afe_clk_ver; int mi2s_clk_count[MI2S_COUNT]; };
@@ -192,6 +198,28 @@ static int qdsp6_dai_get_lpass_id(struct snd_soc_dai *cpu_dai) } }
+static int qdsp6_get_clk_id(struct apq8016_sbc_data *data, int mi2s_id) +{ + if (data->q6afe_clk_ver == Q6AFE_CLK_V2) { + switch (mi2s_id) { + case MI2S_PRIMARY: + return Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT; + case MI2S_SECONDARY: + return Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT; + case MI2S_TERTIARY: + return Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT; + case MI2S_QUATERNARY: + return Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT; + case MI2S_QUINARY: + return Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT; + default: + break; + } + } + /* If AFE CLK isn't V2 return V1 */ + return LPAIF_BIT_CLK; +} + static int msm8916_qdsp6_dai_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); @@ -215,7 +243,7 @@ static int msm8916_qdsp6_startup(struct snd_pcm_substream *substream) if (++data->mi2s_clk_count[mi2s] > 1) return 0;
- ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_BIT_CLK, MI2S_BCLK_RATE, 0); + ret = snd_soc_dai_set_sysclk(cpu_dai, qdsp6_get_clk_id(data, mi2s), MI2S_BCLK_RATE, 0); if (ret) dev_err(card->dev, "Failed to enable LPAIF bit clk: %d\n", ret); return ret; @@ -236,7 +264,7 @@ static void msm8916_qdsp6_shutdown(struct snd_pcm_substream *substream) if (--data->mi2s_clk_count[mi2s] > 0) return;
- ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_BIT_CLK, 0, 0); + ret = snd_soc_dai_set_sysclk(cpu_dai, qdsp6_get_clk_id(data, mi2s), 0, 0); if (ret) dev_err(card->dev, "Failed to disable LPAIF bit clk: %d\n", ret); } @@ -265,10 +293,12 @@ static int msm8916_qdsp6_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, static void msm8916_qdsp6_add_ops(struct snd_soc_card *card) { struct snd_soc_dai_link *link; + struct apq8016_sbc_data *pdata = snd_soc_card_get_drvdata(card); int i;
/* Make it obvious to userspace that QDSP6 is used */ card->components = "qdsp6"; + pdata->q6afe_clk_ver = Q6AFE_CLK_V1;
for_each_card_prelinks(card, i, link) { if (link->no_pcm) { @@ -279,6 +309,14 @@ static void msm8916_qdsp6_add_ops(struct snd_soc_card *card) } }
+static void msm8953_qdsp6_add_ops(struct snd_soc_card *card) +{ + struct apq8016_sbc_data *pdata = snd_soc_card_get_drvdata(card); + + msm8916_qdsp6_add_ops(card); + pdata->q6afe_clk_ver = Q6AFE_CLK_V2; +} + static const struct snd_kcontrol_new apq8016_sbc_snd_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Mic Jack"), @@ -344,6 +382,7 @@ static int apq8016_sbc_platform_probe(struct platform_device *pdev) static const struct of_device_id apq8016_sbc_device_id[] __maybe_unused = { { .compatible = "qcom,apq8016-sbc-sndcard", .data = apq8016_sbc_add_ops }, { .compatible = "qcom,msm8916-qdsp6-sndcard", .data = msm8916_qdsp6_add_ops }, + { .compatible = "qcom,msm8953-qdsp6-sndcard", .data = msm8953_qdsp6_add_ops }, {}, }; MODULE_DEVICE_TABLE(of, apq8016_sbc_device_id);
On Wed, Jul 31, 2024 at 05:25:30PM GMT, Adam Skladowski wrote:
From: Vladimir Lypak vladimir.lypak@gmail.com
Introduce support for audio card on MSM8953 platform. Main difference between MSM8953 and MSM8916 is Q6AFE CLK API supported by firmware which influence way we set codec clocks. SoCs shipping on at least msm-3.18 should use v2 clocks.
Signed-off-by: Vladimir Lypak vladimir.lypak@gmail.com [Adam: rename functions, add msg] Co-developed-by: Adam Skladowski a39.skl@gmail.com Signed-off-by: Adam Skladowski a39.skl@gmail.com
sound/soc/qcom/apq8016_sbc.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-)
Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org
On Wed, Jul 31, 2024 at 05:25:30PM +0200, Adam Skladowski wrote:
From: Vladimir Lypak vladimir.lypak@gmail.com
Introduce support for audio card on MSM8953 platform. Main difference between MSM8953 and MSM8916 is Q6AFE CLK API supported by firmware which influence way we set codec clocks. SoCs shipping on at least msm-3.18 should use v2 clocks.
Signed-off-by: Vladimir Lypak vladimir.lypak@gmail.com [Adam: rename functions, add msg] Co-developed-by: Adam Skladowski a39.skl@gmail.com Signed-off-by: Adam Skladowski a39.skl@gmail.com
sound/soc/qcom/apq8016_sbc.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-)
diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 5a29adbd3f82..3ed35beb671a 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -22,6 +22,11 @@
#define MI2S_COUNT (MI2S_QUINARY + 1)
+enum afe_clk_api {
- Q6AFE_CLK_V1,
- Q6AFE_CLK_V2
+};
struct apq8016_sbc_data { struct snd_soc_card card; void __iomem *mic_iomux; @@ -29,6 +34,7 @@ struct apq8016_sbc_data { void __iomem *quin_iomux; struct snd_soc_jack jack; bool jack_setup;
- enum afe_clk_api q6afe_clk_ver; int mi2s_clk_count[MI2S_COUNT];
};
@@ -192,6 +198,28 @@ static int qdsp6_dai_get_lpass_id(struct snd_soc_dai *cpu_dai) } }
+static int qdsp6_get_clk_id(struct apq8016_sbc_data *data, int mi2s_id) +{
- if (data->q6afe_clk_ver == Q6AFE_CLK_V2) {
switch (mi2s_id) {
case MI2S_PRIMARY:
return Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT;
case MI2S_SECONDARY:
return Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT;
case MI2S_TERTIARY:
return Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT;
case MI2S_QUATERNARY:
return Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT;
case MI2S_QUINARY:
return Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT;
default:
break;
}
- }
- /* If AFE CLK isn't V2 return V1 */
- return LPAIF_BIT_CLK;
+}
static int msm8916_qdsp6_dai_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); @@ -215,7 +243,7 @@ static int msm8916_qdsp6_startup(struct snd_pcm_substream *substream) if (++data->mi2s_clk_count[mi2s] > 1) return 0;
- ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_BIT_CLK, MI2S_BCLK_RATE, 0);
- ret = snd_soc_dai_set_sysclk(cpu_dai, qdsp6_get_clk_id(data, mi2s), MI2S_BCLK_RATE, 0); if (ret) dev_err(card->dev, "Failed to enable LPAIF bit clk: %d\n", ret); return ret;
@@ -236,7 +264,7 @@ static void msm8916_qdsp6_shutdown(struct snd_pcm_substream *substream) if (--data->mi2s_clk_count[mi2s] > 0) return;
- ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_BIT_CLK, 0, 0);
- ret = snd_soc_dai_set_sysclk(cpu_dai, qdsp6_get_clk_id(data, mi2s), 0, 0); if (ret) dev_err(card->dev, "Failed to disable LPAIF bit clk: %d\n", ret);
} @@ -265,10 +293,12 @@ static int msm8916_qdsp6_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, static void msm8916_qdsp6_add_ops(struct snd_soc_card *card) { struct snd_soc_dai_link *link;
struct apq8016_sbc_data *pdata = snd_soc_card_get_drvdata(card); int i;
/* Make it obvious to userspace that QDSP6 is used */ card->components = "qdsp6";
pdata->q6afe_clk_ver = Q6AFE_CLK_V1;
for_each_card_prelinks(card, i, link) { if (link->no_pcm) {
@@ -279,6 +309,14 @@ static void msm8916_qdsp6_add_ops(struct snd_soc_card *card) } }
+static void msm8953_qdsp6_add_ops(struct snd_soc_card *card) +{
- struct apq8016_sbc_data *pdata = snd_soc_card_get_drvdata(card);
- msm8916_qdsp6_add_ops(card);
- pdata->q6afe_clk_ver = Q6AFE_CLK_V2;
+}
Is there a particular reason why you decided to hardcode the q6afe_clk_ver for the SoCs rather than finishing up the dynamic detection Otto proposed [1]?
This works for MSM8953 but there are a few SoCs like MSM8909 where both clock API versions exist (depending on the firmware versions). If we want to support them at some point, we will need the dynamic detection anyway. It would be nice to finish up that patch set.
Thanks, Stephan
[1]: https://lore.kernel.org/linux-arm-msm/20231029165716.69878-1-otto.pflueger@a...
On 8/1/24 12:47, Stephan Gerhold wrote:
On Wed, Jul 31, 2024 at 05:25:30PM +0200, Adam Skladowski wrote:
From: Vladimir Lypak vladimir.lypak@gmail.com
Introduce support for audio card on MSM8953 platform. Main difference between MSM8953 and MSM8916 is Q6AFE CLK API supported by firmware which influence way we set codec clocks. SoCs shipping on at least msm-3.18 should use v2 clocks.
Signed-off-by: Vladimir Lypak vladimir.lypak@gmail.com [Adam: rename functions, add msg] Co-developed-by: Adam Skladowski a39.skl@gmail.com Signed-off-by: Adam Skladowski a39.skl@gmail.com
sound/soc/qcom/apq8016_sbc.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-)
diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 5a29adbd3f82..3ed35beb671a 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -22,6 +22,11 @@
Is there a particular reason why you decided to hardcode the q6afe_clk_ver for the SoCs rather than finishing up the dynamic detection Otto proposed [1]?
This works for MSM8953 but there are a few SoCs like MSM8909 where both clock API versions exist (depending on the firmware versions). If we want to support them at some point, we will need the dynamic detection anyway. It would be nice to finish up that patch set.
Thanks, Stephan
This probably sound obvious but i don't understand takes Srinivas had on these patches. On top i don't feel good sending code i don't understand much. On a note i managed to slightly modify fallback commit and provide match table translating new clks into v1. In theory if we want we can drop snd_soc_component_set_sysclk() from soundcard driver and use devm_clk_get/clk_set_rate/clk_prepare_enable to manage clocks provided by q6afe_clocks. Biggest issue for me is lack of people who i can even discuss with about, even here i fail to see much feedback.
Introduce support for audio card on MSM8976 platform. While MSM8976 falls into v1 category with MSM8916, digitial codec clock is not available in GCC so we have to set it in machine driver. For that reason for V1 clocks new boolean is added to check if we need to enable codec clock.
Signed-off-by: Adam Skladowski a39.skl@gmail.com --- sound/soc/qcom/apq8016_sbc.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 3ed35beb671a..8219d4d55625 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -35,6 +35,7 @@ struct apq8016_sbc_data { struct snd_soc_jack jack; bool jack_setup; enum afe_clk_api q6afe_clk_ver; + bool dig_cdc_mclk_en; int mi2s_clk_count[MI2S_COUNT]; };
@@ -242,6 +243,16 @@ static int msm8916_qdsp6_startup(struct snd_pcm_substream *substream)
if (++data->mi2s_clk_count[mi2s] > 1) return 0; + /* + * On newer legacy SoC (MSM8976) lpass codec clocks are not available in gcc region + * so we have to request clock from machine driver using V1 API) + */ + if (data->q6afe_clk_ver == Q6AFE_CLK_V1 && + data->dig_cdc_mclk_en) { + ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_DIG_CLK, DEFAULT_MCLK_RATE, 0); + if (ret) + dev_err(card->dev, "Failed to enable LPAIF dig clk: %d\n", ret); + }
ret = snd_soc_dai_set_sysclk(cpu_dai, qdsp6_get_clk_id(data, mi2s), MI2S_BCLK_RATE, 0); if (ret) @@ -267,6 +278,13 @@ static void msm8916_qdsp6_shutdown(struct snd_pcm_substream *substream) ret = snd_soc_dai_set_sysclk(cpu_dai, qdsp6_get_clk_id(data, mi2s), 0, 0); if (ret) dev_err(card->dev, "Failed to disable LPAIF bit clk: %d\n", ret); + + if (data->q6afe_clk_ver == Q6AFE_CLK_V1 && + data->dig_cdc_mclk_en) { + ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_DIG_CLK, 0, 0); + if (ret) + dev_err(card->dev, "Failed to disable LPAIF dig clk: %d\n", ret); + } }
static const struct snd_soc_ops msm8916_qdsp6_be_ops = { @@ -317,6 +335,15 @@ static void msm8953_qdsp6_add_ops(struct snd_soc_card *card) pdata->q6afe_clk_ver = Q6AFE_CLK_V2; }
+static void msm8976_qdsp6_add_ops(struct snd_soc_card *card) +{ + struct apq8016_sbc_data *pdata = snd_soc_card_get_drvdata(card); + + msm8916_qdsp6_add_ops(card); + pdata->q6afe_clk_ver = Q6AFE_CLK_V1; + pdata->dig_cdc_mclk_en = true; +} + static const struct snd_kcontrol_new apq8016_sbc_snd_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Mic Jack"), @@ -383,6 +410,7 @@ static const struct of_device_id apq8016_sbc_device_id[] __maybe_unused = { { .compatible = "qcom,apq8016-sbc-sndcard", .data = apq8016_sbc_add_ops }, { .compatible = "qcom,msm8916-qdsp6-sndcard", .data = msm8916_qdsp6_add_ops }, { .compatible = "qcom,msm8953-qdsp6-sndcard", .data = msm8953_qdsp6_add_ops }, + { .compatible = "qcom,msm8976-qdsp6-sndcard", .data = msm8976_qdsp6_add_ops }, {}, }; MODULE_DEVICE_TABLE(of, apq8016_sbc_device_id);
On Wed, Jul 31, 2024 at 05:25:31PM GMT, Adam Skladowski wrote:
Introduce support for audio card on MSM8976 platform. While MSM8976 falls into v1 category with MSM8916, digitial codec clock is not available in GCC so we have to set it in machine driver. For that reason for V1 clocks new boolean is added to check if we need to enable codec clock.
Signed-off-by: Adam Skladowski a39.skl@gmail.com
sound/soc/qcom/apq8016_sbc.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org
On Wed, Jul 31, 2024 at 05:25:31PM +0200, Adam Skladowski wrote:
Introduce support for audio card on MSM8976 platform. While MSM8976 falls into v1 category with MSM8916, digitial codec clock is not available in GCC so we have to set it in machine driver. For that reason for V1 clocks new boolean is added to check if we need to enable codec clock.
Signed-off-by: Adam Skladowski a39.skl@gmail.com
sound/soc/qcom/apq8016_sbc.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 3ed35beb671a..8219d4d55625 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -35,6 +35,7 @@ struct apq8016_sbc_data { struct snd_soc_jack jack; bool jack_setup; enum afe_clk_api q6afe_clk_ver;
- bool dig_cdc_mclk_en; int mi2s_clk_count[MI2S_COUNT];
};
@@ -242,6 +243,16 @@ static int msm8916_qdsp6_startup(struct snd_pcm_substream *substream)
if (++data->mi2s_clk_count[mi2s] > 1) return 0;
/*
* On newer legacy SoC (MSM8976) lpass codec clocks are not available in gcc region
* so we have to request clock from machine driver using V1 API)
*/
if (data->q6afe_clk_ver == Q6AFE_CLK_V1 &&
data->dig_cdc_mclk_en) {
ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_DIG_CLK, DEFAULT_MCLK_RATE, 0);
if (ret)
dev_err(card->dev, "Failed to enable LPAIF dig clk: %d\n", ret);
}
ret = snd_soc_dai_set_sysclk(cpu_dai, qdsp6_get_clk_id(data, mi2s), MI2S_BCLK_RATE, 0); if (ret)
@@ -267,6 +278,13 @@ static void msm8916_qdsp6_shutdown(struct snd_pcm_substream *substream) ret = snd_soc_dai_set_sysclk(cpu_dai, qdsp6_get_clk_id(data, mi2s), 0, 0); if (ret) dev_err(card->dev, "Failed to disable LPAIF bit clk: %d\n", ret);
- if (data->q6afe_clk_ver == Q6AFE_CLK_V1 &&
data->dig_cdc_mclk_en) {
ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_DIG_CLK, 0, 0);
if (ret)
dev_err(card->dev, "Failed to disable LPAIF dig clk: %d\n", ret);
- }
}
I'm a bit confused why this works correctly. The digital codec clock (mclk) is needed whenever accessing registers of the digital codec ("qcom,msm8916-wcd-digital-codec"). This is why the clock is directly assigned to it in the DT, so the codec driver can request it when needed. The startup/shutdown callbacks in this patch are only called during audio playback, while the codec registers might be accessed any time e.g. when changing the volume mixers. Perhaps you are lucky not to hit that, but if the clock is off at that point the device will crash or hang.
Instead of requesting the clock here, we should assign it to the digital codec in the DT. I think Otto's series also allowed that for the older v1 firmware [1]. Can we work towards finishing that up instead? That should be more reliable.
Thanks, Stephan
[1]: https://lore.kernel.org/linux-arm-msm/20231029165716.69878-1-otto.pflueger@a...
On 31.07.2024 5:25 PM, Adam Skladowski wrote:
Introduce support for audio card on MSM8976 platform. While MSM8976 falls into v1 category with MSM8916, digitial codec clock is not available in GCC so we have to set it in machine driver. For that reason for V1 clocks new boolean is added to check if we need to enable codec clock.
Signed-off-by: Adam Skladowski a39.skl@gmail.com
sound/soc/qcom/apq8016_sbc.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 3ed35beb671a..8219d4d55625 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -35,6 +35,7 @@ struct apq8016_sbc_data { struct snd_soc_jack jack; bool jack_setup; enum afe_clk_api q6afe_clk_ver;
- bool dig_cdc_mclk_en; int mi2s_clk_count[MI2S_COUNT];
};
@@ -242,6 +243,16 @@ static int msm8916_qdsp6_startup(struct snd_pcm_substream *substream)
if (++data->mi2s_clk_count[mi2s] > 1) return 0;
- /*
* On newer legacy SoC (MSM8976) lpass codec clocks are not available in gcc region
* so we have to request clock from machine driver using V1 API)
*/
- if (data->q6afe_clk_ver == Q6AFE_CLK_V1 &&
data->dig_cdc_mclk_en) {
ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_DIG_CLK, DEFAULT_MCLK_RATE, 0);
Double space here and below
Konrad
From: Vladimir Lypak vladimir.lypak@gmail.com
Add descriptions and controls to toggle lineout output
Signed-off-by: Vladimir Lypak vladimir.lypak@gmail.com Signed-off-by: Adam Skladowski a39.skl@gmail.com --- sound/soc/codecs/msm8916-wcd-analog.c | 64 +++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+)
diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c index b9325290c28d..38949556f7d9 100644 --- a/sound/soc/codecs/msm8916-wcd-analog.c +++ b/sound/soc/codecs/msm8916-wcd-analog.c @@ -233,6 +233,8 @@ #define RX_EAR_CTL_PA_SEL BIT(7)
#define CDC_A_RX_EAR_STATUS (0xf1A1) +#define CDC_A_RX_LO_DAC_CTL (0xf1AC) +#define CDC_A_RX_LO_EN_CTL (0xf1AD)
#define CDC_A_SPKR_DAC_CTL (0xf1B0) #define SPKR_DAC_CTL_DAC_RESET_MASK BIT(4) @@ -327,6 +329,8 @@ static const struct soc_enum hph_enum = SOC_ENUM_SINGLE_VIRT( static const struct snd_kcontrol_new ear_mux = SOC_DAPM_ENUM("EAR_S", hph_enum); static const struct snd_kcontrol_new hphl_mux = SOC_DAPM_ENUM("HPHL", hph_enum); static const struct snd_kcontrol_new hphr_mux = SOC_DAPM_ENUM("HPHR", hph_enum); +static const struct snd_kcontrol_new lineout_mux = SOC_DAPM_ENUM("LINEOUT", + hph_enum);
/* ADC2 MUX */ static const struct soc_enum adc2_enum = SOC_ENUM_SINGLE_VIRT( @@ -630,6 +634,46 @@ static int pm8916_wcd_analog_enable_adc(struct snd_soc_dapm_widget *w, return 0; }
+static int pm8916_wcd_analog_enable_lineout_dac(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_component_update_bits(component, CDC_A_RX_LO_EN_CTL, + 0x20, 0x20); + snd_soc_component_update_bits(component, CDC_A_RX_LO_EN_CTL, + 0x80, 0x80); + snd_soc_component_update_bits(component, CDC_A_RX_LO_DAC_CTL, + 0x08, 0x08); + snd_soc_component_update_bits(component, CDC_A_RX_LO_DAC_CTL, + 0x40, 0x40); + break; + case SND_SOC_DAPM_POST_PMU: + snd_soc_component_update_bits(component, CDC_A_RX_LO_DAC_CTL, + 0x80, 0x80); + snd_soc_component_update_bits(component, CDC_A_RX_LO_DAC_CTL, + 0x08, 0x00); + break; + case SND_SOC_DAPM_POST_PMD: + usleep_range(20000, 20100); + snd_soc_component_update_bits(component, CDC_A_RX_LO_DAC_CTL, + 0x80, 0x00); + snd_soc_component_update_bits(component, CDC_A_RX_LO_DAC_CTL, + 0x40, 0x00); + snd_soc_component_update_bits(component, CDC_A_RX_LO_DAC_CTL, + 0x08, 0x00); + snd_soc_component_update_bits(component, CDC_A_RX_LO_EN_CTL, + 0x80, 0x00); + snd_soc_component_update_bits(component, CDC_A_RX_LO_EN_CTL, + 0x20, 0x00); + break; + } + return 0; +} + static int pm8916_wcd_analog_enable_spk_pa(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) @@ -917,6 +961,13 @@ static const struct snd_soc_dapm_route pm8916_wcd_analog_audio_map[] = { {"SPK PA", NULL, "SPK DAC"}, {"SPK DAC", "Switch", "PDM_RX3"},
+ {"LINEOUT_OUT", NULL, "LINEOUT PA"}, + {"LINEOUT PA", NULL, "RX_BIAS"}, + {"LINEOUT PA", NULL, "SPKR_CLK"}, + {"LINEOUT PA", NULL, "LINEOUT"}, + {"LINEOUT", "Switch", "LINEOUT DAC"}, + {"LINEOUT DAC", NULL, "PDM_RX3"}, + {"MIC_BIAS1", NULL, "INT_LDO_H"}, {"MIC_BIAS2", NULL, "INT_LDO_H"}, {"MIC_BIAS1", NULL, "vdd-micbias"}, @@ -978,6 +1029,19 @@ static const struct snd_soc_dapm_widget pm8916_wcd_analog_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("DAC_REF", CDC_A_RX_COM_BIAS_DAC, 0, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("RX_BIAS", CDC_A_RX_COM_BIAS_DAC, 7, 0, NULL, 0),
+ /* Lineout */ + SND_SOC_DAPM_OUTPUT("LINEOUT_OUT"), + + SND_SOC_DAPM_PGA_E("LINEOUT PA", CDC_A_RX_LO_EN_CTL, + 6, 0, NULL, 0, NULL, 0), + + SND_SOC_DAPM_DAC_E("LINEOUT DAC", NULL, SND_SOC_NOPM, 0, 0, + pm8916_wcd_analog_enable_lineout_dac, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX("LINEOUT", SND_SOC_NOPM, 0, 0, &lineout_mux), + /* TX */ SND_SOC_DAPM_SUPPLY("MIC_BIAS1", CDC_A_MICB_1_EN, 7, 0, pm8916_wcd_analog_enable_micbias1,
On 31.07.2024 5:25 PM, Adam Skladowski wrote:
From: Vladimir Lypak vladimir.lypak@gmail.com
Add descriptions and controls to toggle lineout output
Signed-off-by: Vladimir Lypak vladimir.lypak@gmail.com Signed-off-by: Adam Skladowski a39.skl@gmail.com
sound/soc/codecs/msm8916-wcd-analog.c | 64 +++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+)
diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c index b9325290c28d..38949556f7d9 100644 --- a/sound/soc/codecs/msm8916-wcd-analog.c +++ b/sound/soc/codecs/msm8916-wcd-analog.c @@ -233,6 +233,8 @@ #define RX_EAR_CTL_PA_SEL BIT(7)
#define CDC_A_RX_EAR_STATUS (0xf1A1) +#define CDC_A_RX_LO_DAC_CTL (0xf1AC) +#define CDC_A_RX_LO_EN_CTL (0xf1AD)
#define CDC_A_SPKR_DAC_CTL (0xf1B0) #define SPKR_DAC_CTL_DAC_RESET_MASK BIT(4) @@ -327,6 +329,8 @@ static const struct soc_enum hph_enum = SOC_ENUM_SINGLE_VIRT( static const struct snd_kcontrol_new ear_mux = SOC_DAPM_ENUM("EAR_S", hph_enum); static const struct snd_kcontrol_new hphl_mux = SOC_DAPM_ENUM("HPHL", hph_enum); static const struct snd_kcontrol_new hphr_mux = SOC_DAPM_ENUM("HPHR", hph_enum); +static const struct snd_kcontrol_new lineout_mux = SOC_DAPM_ENUM("LINEOUT",
hph_enum);
/* ADC2 MUX */ static const struct soc_enum adc2_enum = SOC_ENUM_SINGLE_VIRT( @@ -630,6 +634,46 @@ static int pm8916_wcd_analog_enable_adc(struct snd_soc_dapm_widget *w, return 0; }
+static int pm8916_wcd_analog_enable_lineout_dac(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
+{
- struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
snd_soc_component_update_bits(component, CDC_A_RX_LO_EN_CTL,
0x20, 0x20);
Using BIT(n) here would be nicer, but this looks reasonable otherwise
Konrad
participants (6)
-
Adam Skladowski
-
Dmitry Baryshkov
-
Konrad Dybcio
-
Konrad Dybcio
-
Krzysztof Kozlowski
-
Stephan Gerhold