[PATCH v2 0/4] 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.
[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
Adam Skladowski (1): ASoC: dt-bindings: apq8016-sbc: Add msm8953/msm8976-qdsp6-sndcard
Vladimir Lypak (3): ASoC: qcom: apq8016_sbc.c: Add Quinary support ASoC: msm8916-wcd-analog: add cajon and cajon v2 support ASoC: qcom: apq8016_sbc: Add support for msm8953/msm8976 SoC
.../sound/qcom,apq8016-sbc-sndcard.yaml | 51 +++++++++-- sound/soc/codecs/msm8916-wcd-analog.c | 63 +++++++++++++- sound/soc/qcom/apq8016_sbc.c | 84 ++++++++++++++++++- 3 files changed, 186 insertions(+), 12 deletions(-)
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 | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 3023cf180a75..303dd88206b1 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,9 @@ 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"); + data->quin_iomux = devm_ioremap_resource(&pdev->dev, res); + snd_soc_card_set_drvdata(card, data);
add_ops(card);
On Sat, Jul 27, 2024 at 08:20:24PM 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 | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
[...]
@@ -320,6 +331,9 @@ 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");
- data->quin_iomux = devm_ioremap_resource(&pdev->dev, res);
This will still print an error if there is no quin-iomux. It's better to call devm_ioremap_resource() only if res is not NULL.
LGTM otherwise
snd_soc_card_set_drvdata(card, data);
add_ops(card);
-- 2.45.2
Document MSM8953/MSM8976 QDSP6 cards.
Signed-off-by: Adam Skladowski a39.skl@gmail.com --- .../sound/qcom,apq8016-sbc-sndcard.yaml | 51 ++++++++++++++++--- 1 file changed, 45 insertions(+), 6 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc-sndcard.yaml b/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc-sndcard.yaml index 6ad451549036..1706ce334d2f 100644 --- a/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc-sndcard.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc-sndcard.yaml @@ -15,16 +15,16 @@ properties: enum: - qcom,apq8016-sbc-sndcard - qcom,msm8916-qdsp6-sndcard + - qcom,msm8953-qdsp6-sndcard + - qcom,msm8976-qdsp6-sndcard
reg: - items: - - description: Microphone I/O mux register address - - description: Speaker I/O mux register address + minItems: 2 + maxItems: 3
reg-names: - items: - - const: mic-iomux - - const: spkr-iomux + minItems: 2 + maxItems: 3
audio-routing: $ref: /schemas/types.yaml#/definitions/non-unique-string-array @@ -106,6 +106,45 @@ required: - reg-names - model
+allOf: + - if: + properties: + compatible: + contains: + enum: + - qcom,apq8016-sbc-sndcard + - qcom,msm8916-qdsp6-sndcard + then: + properties: + reg: + items: + - description: Microphone I/O mux register address + - description: Speaker I/O mux register address + reg-names: + items: + - const: mic-iomux + - const: spkr-iomux + + - if: + properties: + compatible: + contains: + enum: + - qcom,msm8953-qdsp6-sndcard + - qcom,msm8976-qdsp6-sndcard + then: + properties: + reg: + 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: + items: + - const: mic-iomux + - const: spkr-iomux + - const: quin-iomux + additionalProperties: false
examples:
On Sat, Jul 27, 2024 at 08:20:26PM GMT, Adam Skladowski wrote:
Document MSM8953/MSM8976 QDSP6 cards.
Signed-off-by: Adam Skladowski a39.skl@gmail.com
.../sound/qcom,apq8016-sbc-sndcard.yaml | 51 ++++++++++++++++--- 1 file changed, 45 insertions(+), 6 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc-sndcard.yaml b/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc-sndcard.yaml index 6ad451549036..1706ce334d2f 100644 --- a/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc-sndcard.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc-sndcard.yaml @@ -15,16 +15,16 @@ properties: enum: - qcom,apq8016-sbc-sndcard - qcom,msm8916-qdsp6-sndcard
- qcom,msm8953-qdsp6-sndcard
- qcom,msm8976-qdsp6-sndcard
reg:
- items:
- description: Microphone I/O mux register address
- description: Speaker I/O mux register address
minItems: 2
maxItems: 3
reg-names:
- items:
- const: mic-iomux
- const: spkr-iomux
minItems: 2
maxItems: 3
audio-routing: $ref: /schemas/types.yaml#/definitions/non-unique-string-array
@@ -106,6 +106,45 @@ required:
- reg-names
- model
+allOf:
- if:
properties:
compatible:
contains:
enum:
- qcom,apq8016-sbc-sndcard
- qcom,msm8916-qdsp6-sndcard
- then:
properties:
reg:
items:
- description: Microphone I/O mux register address
- description: Speaker I/O mux register address
reg-names:
items:
- const: mic-iomux
- const: spkr-iomux
- if:
properties:
compatible:
contains:
enum:
- qcom,msm8953-qdsp6-sndcard
- qcom,msm8976-qdsp6-sndcard
- then:
properties:
reg:
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:
items:
- const: mic-iomux
- const: spkr-iomux
- const: quin-iomux
As msm8953 / msm8976 just add one new region it might be better to move the lists back to top-level definitions (still having mix/maxItems next to it) and then in the conditional branches just specify maxItems:2 for apq8016/msm8916 and maxItems:3 for msm8953/msm8976.
This way it becomes:
reg: items: - description: Microphone I/O mux register address - description: Speaker I/O mux register address minItems: 2 maxItems: 3
# same for reg-names
[....]
- 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: maxItems: 3 reg-names: maxItems: 3
additionalProperties: false
examples:
2.45.2
On 27/07/2024 20:20, Adam Skladowski wrote:
Document MSM8953/MSM8976 QDSP6 cards.
Signed-off-by: Adam Skladowski a39.skl@gmail.com
Your cover letter must ALWAYS clearly document the dependency.
.../sound/qcom,apq8016-sbc-sndcard.yaml | 51 ++++++++++++++++--- 1 file changed, 45 insertions(+), 6 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc-sndcard.yaml b/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc-sndcard.yaml index 6ad451549036..1706ce334d2f 100644 --- a/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc-sndcard.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc-sndcard.yaml @@ -15,16 +15,16 @@ properties: enum: - qcom,apq8016-sbc-sndcard - qcom,msm8916-qdsp6-sndcard
- qcom,msm8953-qdsp6-sndcard
- qcom,msm8976-qdsp6-sndcard
reg:
- items:
- description: Microphone I/O mux register address
- description: Speaker I/O mux register address
As I explained you on IRC, grow the list here and add minItems
minItems: 2
maxItems: 3
reg-names:
- items:
As I explained you on IRC, grow the list here and add minItems
- const: mic-iomux
- const: spkr-iomux
minItems: 2
maxItems: 3
audio-routing: $ref: /schemas/types.yaml#/definitions/non-unique-string-array
@@ -106,6 +106,45 @@ required:
- reg-names
- model
+allOf:
- if:
properties:
compatible:
contains:
enum:
- qcom,apq8016-sbc-sndcard
- qcom,msm8916-qdsp6-sndcard
- then:
properties:
reg:
maxItems: 2
items:
- description: Microphone I/O mux register address
- description: Speaker I/O mux register address
reg-names:
maxItems :2
items:
- const: mic-iomux
- const: spkr-iomux
- if:
properties:
compatible:
contains:
enum:
- qcom,msm8953-qdsp6-sndcard
- qcom,msm8976-qdsp6-sndcard
- then:
properties:
reg:
minItems: 3
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: 3
Best regards, Krzysztof
From: Vladimir Lypak vladimir.lypak@gmail.com
Introduce support for audio card on MSM8953/MSM8976 platform. Main difference between those two is Q6AFE CLK API supported by firmware which influence way we enable digital codec clock. Either inside machine driver or outside via q6afe-clocks driver.
Signed-off-by: Vladimir Lypak vladimir.lypak@gmail.com [Adam: Add MSM8976, rename functions, add mclk setting,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 | 68 ++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 2 deletions(-)
diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 303dd88206b1..453ca4795603 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,8 @@ struct apq8016_sbc_data { void __iomem *quin_iomux; 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]; };
@@ -192,6 +199,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); @@ -214,8 +243,17 @@ 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 == true) { + 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, 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,9 +274,16 @@ 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); + + if (data->q6afe_clk_ver == Q6AFE_CLK_V1 && data->dig_cdc_mclk_en == true) { + 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 = { @@ -279,6 +324,23 @@ 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); + + pdata->q6afe_clk_ver = Q6AFE_CLK_V2; + msm8916_qdsp6_add_ops(card); +} + +static void msm8976_qdsp6_add_ops(struct snd_soc_card *card) +{ + struct apq8016_sbc_data *pdata = snd_soc_card_get_drvdata(card); + + pdata->q6afe_clk_ver = Q6AFE_CLK_V1; + pdata->dig_cdc_mclk_en = true; + msm8916_qdsp6_add_ops(card); +} + static const struct snd_kcontrol_new apq8016_sbc_snd_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Mic Jack"), @@ -343,6 +405,8 @@ 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 }, + { .compatible = "qcom,msm8976-qdsp6-sndcard", .data = msm8976_qdsp6_add_ops }, {}, }; MODULE_DEVICE_TABLE(of, apq8016_sbc_device_id);
On Sat, Jul 27, 2024 at 08:20:27PM GMT, Adam Skladowski wrote:
From: Vladimir Lypak vladimir.lypak@gmail.com
Introduce support for audio card on MSM8953/MSM8976 platform. Main difference between those two is Q6AFE CLK API supported by firmware which influence way we enable digital codec clock. Either inside machine driver or outside via q6afe-clocks driver.
Signed-off-by: Vladimir Lypak vladimir.lypak@gmail.com [Adam: Add MSM8976, rename functions, add mclk setting,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 | 68 ++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 2 deletions(-)
diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 303dd88206b1..453ca4795603 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
+};
Are these v1/v2 coming from some msm-N.M kernel? It's not obvious from the patch, but msm8916 also falls into v1 category. Is that expected?
struct apq8016_sbc_data { struct snd_soc_card card; void __iomem *mic_iomux; @@ -29,6 +34,8 @@ struct apq8016_sbc_data { void __iomem *quin_iomux; 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];
};
@@ -192,6 +199,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); @@ -214,8 +243,17 @@ 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 == true) {
Nit: line feed after &&
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, 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,9 +274,16 @@ 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);
- if (data->q6afe_clk_ver == Q6AFE_CLK_V1 && data->dig_cdc_mclk_en == true) {
Nit: And here too, please.
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 = { @@ -279,6 +324,23 @@ 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);
- pdata->q6afe_clk_ver = Q6AFE_CLK_V2;
- msm8916_qdsp6_add_ops(card);
+}
+static void msm8976_qdsp6_add_ops(struct snd_soc_card *card) +{
- struct apq8016_sbc_data *pdata = snd_soc_card_get_drvdata(card);
- pdata->q6afe_clk_ver = Q6AFE_CLK_V1;
- pdata->dig_cdc_mclk_en = true;
- msm8916_qdsp6_add_ops(card);
+}
static const struct snd_kcontrol_new apq8016_sbc_snd_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Mic Jack"), @@ -343,6 +405,8 @@ 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 },
- { .compatible = "qcom,msm8976-qdsp6-sndcard", .data = msm8976_qdsp6_add_ops }, {},
}; MODULE_DEVICE_TABLE(of, apq8016_sbc_device_id); -- 2.45.2
From: Vladimir Lypak vladimir.lypak@gmail.com
Add regs overrides for Cajon(PM8952) and Cajon v2(PM8953) codecs.
Signed-off-by: Vladimir Lypak vladimir.lypak@gmail.com [Adam: Add Cajon support,add msg] Co-developed-by: Adam Skladowski a39.skl@gmail.com Signed-off-by: Adam Skladowski a39.skl@gmail.com --- sound/soc/codecs/msm8916-wcd-analog.c | 63 +++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 3 deletions(-)
diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c index 9ca381812975..daf65f5d4e99 100644 --- a/sound/soc/codecs/msm8916-wcd-analog.c +++ b/sound/soc/codecs/msm8916-wcd-analog.c @@ -250,6 +250,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,12 +265,15 @@
#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) #define CDC_A_PERPH_RESET_CTL3 (0xf1DA) #define CDC_A_PERPH_RESET_CTL4 (0xf1DB)
+#define CDC_A_RX_EAR_STATUS (0xf1A1) + #define MSM8916_WCD_ANALOG_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000) #define MSM8916_WCD_ANALOG_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ @@ -715,6 +719,50 @@ static const struct reg_default wcd_reg_defaults_2_0[] = { {CDC_A_MASTER_BIAS_CTL, 0x30}, };
+static const struct reg_default wcd_reg_defaults_cajon[] = { + {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 reg_default wcd_reg_defaults_cajon_2_0[] = { + {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 int pm8916_wcd_analog_probe(struct snd_soc_component *component) { struct pm8916_wcd_analog_priv *priv = dev_get_drvdata(component->dev); @@ -738,9 +786,18 @@ 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); + if (priv->codec_version == 4) + for (reg = 0; reg < ARRAY_SIZE(wcd_reg_defaults_cajon_2_0); reg++) + snd_soc_component_write(component, wcd_reg_defaults_cajon_2_0[reg].reg, + wcd_reg_defaults_cajon_2_0[reg].def); + else if (priv->codec_version == 3) + for (reg = 0; reg < ARRAY_SIZE(wcd_reg_defaults_cajon); reg++) + snd_soc_component_write(component, wcd_reg_defaults_cajon[reg].reg, + wcd_reg_defaults_cajon[reg].def); + else + 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);
priv->component = component;
On Sat, Jul 27, 2024 at 08:20:25PM GMT, Adam Skladowski wrote:
From: Vladimir Lypak vladimir.lypak@gmail.com
Add regs overrides for Cajon(PM8952) and Cajon v2(PM8953) codecs.
Signed-off-by: Vladimir Lypak vladimir.lypak@gmail.com [Adam: Add Cajon support,add msg] Co-developed-by: Adam Skladowski a39.skl@gmail.com Signed-off-by: Adam Skladowski a39.skl@gmail.com
sound/soc/codecs/msm8916-wcd-analog.c | 63 +++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 3 deletions(-)
diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c index 9ca381812975..daf65f5d4e99 100644 --- a/sound/soc/codecs/msm8916-wcd-analog.c +++ b/sound/soc/codecs/msm8916-wcd-analog.c @@ -250,6 +250,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,12 +265,15 @@
#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) #define CDC_A_PERPH_RESET_CTL3 (0xf1DA) #define CDC_A_PERPH_RESET_CTL4 (0xf1DB)
+#define CDC_A_RX_EAR_STATUS (0xf1A1)
This one should go before CDC_A_SPKR_DAC_CTL
#define MSM8916_WCD_ANALOG_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000) #define MSM8916_WCD_ANALOG_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ @@ -715,6 +719,50 @@ static const struct reg_default wcd_reg_defaults_2_0[] = { {CDC_A_MASTER_BIAS_CTL, 0x30}, };
+static const struct reg_default wcd_reg_defaults_cajon[] = {
- {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 reg_default wcd_reg_defaults_cajon_2_0[] = {
- {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 int pm8916_wcd_analog_probe(struct snd_soc_component *component) { struct pm8916_wcd_analog_priv *priv = dev_get_drvdata(component->dev); @@ -738,9 +786,18 @@ 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);
- if (priv->codec_version == 4)
for (reg = 0; reg < ARRAY_SIZE(wcd_reg_defaults_cajon_2_0); reg++)
snd_soc_component_write(component, wcd_reg_defaults_cajon_2_0[reg].reg,
wcd_reg_defaults_cajon_2_0[reg].def);
- else if (priv->codec_version == 3)
for (reg = 0; reg < ARRAY_SIZE(wcd_reg_defaults_cajon); reg++)
snd_soc_component_write(component, wcd_reg_defaults_cajon[reg].reg,
wcd_reg_defaults_cajon[reg].def);
- else
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);
I have mixed feelings towards this. Would it be better to use PMIC-specific compatibles and pass register init as match data instead?
priv->component = component;
-- 2.45.2
participants (3)
-
Adam Skladowski
-
Dmitry Baryshkov
-
Krzysztof Kozlowski