|
@@ -1,6 +1,6 @@
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
|
|
/* Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
|
|
|
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
|
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
|
*/
|
|
|
|
|
|
#include <linux/clk.h>
|
|
@@ -195,6 +195,7 @@ struct msm_asoc_mach_data {
|
|
|
struct snd_soc_codec *codec;
|
|
|
struct work_struct adsp_power_up_work;
|
|
|
struct tdm_conf tdm_intf_conf[TDM_INTERFACE_MAX];
|
|
|
+ struct snd_pcm_hardware hw_params;
|
|
|
};
|
|
|
|
|
|
static const char *const pin_states[] = {"sleep", "i2s-active",
|
|
@@ -225,12 +226,31 @@ static const struct snd_soc_dapm_widget msm_dapm_widgets[] = {
|
|
|
SND_SOC_DAPM_MIC("Digital Mic7", NULL),
|
|
|
};
|
|
|
|
|
|
+static int tdm_snd_startup(struct snd_pcm_substream *substream)
|
|
|
+{
|
|
|
+ int ret = 0;
|
|
|
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
|
|
+ struct snd_soc_card *card = rtd->card;
|
|
|
+ struct snd_soc_dai_link *dai_link = rtd->dai_link;
|
|
|
+ struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
|
|
|
+
|
|
|
+ if (!dai_link->no_pcm)
|
|
|
+ ret = snd_soc_set_runtime_hwparams(substream, &pdata->hw_params);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static const struct snd_soc_ops tdm_be_ops = {
|
|
|
+ .startup = tdm_snd_startup,
|
|
|
+};
|
|
|
+
|
|
|
static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
/* BackEnd DAI Links */
|
|
|
{
|
|
|
.name = "PRI_TDM_RX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF-RX-PRIMARY",
|
|
|
.dpcm_playback = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -241,6 +261,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "PRI_TDM_TX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF-TX-PRIMARY",
|
|
|
.dpcm_capture = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -251,6 +272,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "SEC_TDM_RX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF-RX-SECONDARY",
|
|
|
.dpcm_playback = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -261,6 +283,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "SEC_TDM_TX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF-TX-SECONDARY",
|
|
|
.dpcm_capture = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -271,6 +294,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "TERT_TDM_RX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF-RX-TERTIARY",
|
|
|
.dpcm_playback = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -281,6 +305,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "TERT_TDM_TX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF-TX-TERTIARY",
|
|
|
.dpcm_capture = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -291,6 +316,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "QUAT_TDM_RX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF_RXTX-RX-PRIMARY",
|
|
|
.dpcm_playback = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -301,6 +327,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "QUAT_TDM_TX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF_RXTX-TX-PRIMARY",
|
|
|
.dpcm_capture = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -311,6 +338,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "QUIN_TDM_RX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF_VA-RX-PRIMARY",
|
|
|
.dpcm_playback = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -321,6 +349,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "QUIN_TDM_TX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF_VA-TX-PRIMARY",
|
|
|
.dpcm_capture = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -331,6 +360,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "SEN_TDM_RX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF_WSA-RX-PRIMARY",
|
|
|
.dpcm_playback = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -341,6 +371,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "SEN_TDM_TX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF_WSA-TX-PRIMARY",
|
|
|
.dpcm_capture = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -351,6 +382,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "SEP_TDM_RX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF_AUD-RX-PRIMARY",
|
|
|
.dpcm_playback = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -361,6 +393,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "SEP_TDM_TX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF_AUD-TX-PRIMARY",
|
|
|
.dpcm_capture = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -371,6 +404,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "OCT_TDM_RX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF_WSA2-RX-PRIMARY",
|
|
|
.dpcm_playback = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -381,6 +415,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "OCT_TDM_TX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF_WSA2-TX-PRIMARY",
|
|
|
.dpcm_capture = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -391,6 +426,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "HS_IF0_TDM_RX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF_SDR-RX-PRIMARY",
|
|
|
.dpcm_playback = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -401,6 +437,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "HS_IF0_TDM_TX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF_SDR-TX-PRIMARY",
|
|
|
.dpcm_capture = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -411,6 +448,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "HS_IF1_TDM_RX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF_SDR-RX-SECONDARY",
|
|
|
.dpcm_playback = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -421,6 +459,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "HS_IF1_TDM_TX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF_SDR-TX-SECONDARY",
|
|
|
.dpcm_capture = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -431,6 +470,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "HS_IF2_TDM_RX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF_SDR-RX-TERTIARY",
|
|
|
.dpcm_playback = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -441,6 +481,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "HS_IF2_TDM_TX_0_DUMMY",
|
|
|
.stream_name = "TDM-LPAIF_SDR-TX-TERTIARY",
|
|
|
.dpcm_capture = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -451,6 +492,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "HS_IF3_TDM_RX_0",
|
|
|
.stream_name = "TDM-LPAIF_SDR-RX-QUATERNARY",
|
|
|
.dpcm_playback = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -461,6 +503,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "HS_IF3_TDM_TX_0",
|
|
|
.stream_name = "TDM-LPAIF_SDR-TX-QUATERNARY",
|
|
|
.dpcm_capture = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -471,6 +514,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "HS_IF4_TDM_RX_0",
|
|
|
.stream_name = "TDM-LPAIF_SDR-RX-QUINARY",
|
|
|
.dpcm_playback = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -481,6 +525,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
|
|
|
.name = "HS_IF4_TDM_TX_0",
|
|
|
.stream_name = "TDM-LPAIF_SDR-TX-QUINARY",
|
|
|
.dpcm_capture = 1,
|
|
|
+ .ops = &tdm_be_ops,
|
|
|
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
|
|
|
SND_SOC_DPCM_TRIGGER_POST},
|
|
|
.ignore_suspend = 1,
|
|
@@ -760,6 +805,75 @@ err:
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+static int msm_get_hwparams(struct platform_device *pdev)
|
|
|
+{
|
|
|
+ struct snd_soc_card *card = NULL;
|
|
|
+ struct msm_asoc_mach_data *pdata = NULL;
|
|
|
+ u32 pcm_info = 0;
|
|
|
+ u32 buffer_bytes_max = 0;
|
|
|
+ u32 periods_bytes[2] = {0};
|
|
|
+ u32 periods_count[2] = {0};
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ card = platform_get_drvdata(pdev);
|
|
|
+ if (!card) {
|
|
|
+ pr_err("%s: card is NULL\n",
|
|
|
+ __func__);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ pdata = snd_soc_card_get_drvdata(card);
|
|
|
+ if (!pdata) {
|
|
|
+ pr_err("%s: pdata is NULL\n",
|
|
|
+ __func__);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = of_property_read_u32(pdev->dev.of_node,
|
|
|
+ "qcom,hw_pcm_info",
|
|
|
+ &pcm_info);
|
|
|
+ if (ret) {
|
|
|
+ pr_err("%s: read pcm info failed\n",
|
|
|
+ __func__);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = of_property_read_u32(pdev->dev.of_node,
|
|
|
+ "qcom,hw_buffer_size_max",
|
|
|
+ &buffer_bytes_max);
|
|
|
+ if (ret) {
|
|
|
+ pr_err("%s: read buffer size max failed\n",
|
|
|
+ __func__);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = of_property_read_u32_array(pdev->dev.of_node,
|
|
|
+ "qcom,hw_period_byte_size",
|
|
|
+ periods_bytes, 2);
|
|
|
+ if (ret) {
|
|
|
+ pr_err("%s: read period byte size failed\n",
|
|
|
+ __func__);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = of_property_read_u32_array(pdev->dev.of_node,
|
|
|
+ "qcom,hw_period_count_size",
|
|
|
+ periods_count, 2);
|
|
|
+ if (ret) {
|
|
|
+ pr_err("%s: read period count size failed\n",
|
|
|
+ __func__);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ pdata->hw_params.info = pcm_info;
|
|
|
+ pdata->hw_params.buffer_bytes_max = buffer_bytes_max;
|
|
|
+ pdata->hw_params.period_bytes_min = periods_bytes[0];
|
|
|
+ pdata->hw_params.period_bytes_max = periods_bytes[1];
|
|
|
+ pdata->hw_params.periods_min = periods_count[0];
|
|
|
+ pdata->hw_params.periods_max = periods_count[1];
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
static int msm_asoc_machine_probe(struct platform_device *pdev)
|
|
|
{
|
|
|
struct snd_soc_card *card;
|
|
@@ -819,6 +933,14 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
|
|
|
|
|
|
pr_debug("%s: DRIVER Audio Ready\n", __func__);
|
|
|
|
|
|
+ ret = msm_get_hwparams(pdev);
|
|
|
+ if (ret) {
|
|
|
+ dev_err(&pdev->dev,
|
|
|
+ "%s: hwparams get failed with %d\n",
|
|
|
+ __func__, ret);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
spdev = pdev;
|
|
|
ret = msm_audio_ssr_register(&virt_sndcard_ctl);
|
|
|
if (ret)
|