ASoC: SOF: amd: Add Soundwire DAI configuration support for AMD platforms
authorVijendar Mukunda <Vijendar.Mukunda@amd.com>
Mon, 29 Jan 2024 05:51:43 +0000 (11:21 +0530)
committerMark Brown <broonie@kernel.org>
Tue, 30 Jan 2024 16:06:39 +0000 (16:06 +0000)
Add support for configuring AMD Soundwire DAI from topology.

Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
Link: https://msgid.link/r/20240129055147.1493853-10-Vijendar.Mukunda@amd.com
Signed-off-by: Mark Brown <broonie@kernel.org>
include/sound/sof/dai-amd.h
include/sound/sof/dai.h
include/uapi/sound/sof/tokens.h
sound/soc/sof/ipc3-pcm.c
sound/soc/sof/ipc3-topology.c
sound/soc/sof/sof-audio.h
sound/soc/sof/topology.c

index 9df7ac8..59cd014 100644 (file)
@@ -26,4 +26,11 @@ struct sof_ipc_dai_acpdmic_params {
        uint32_t pdm_ch;
 } __packed;
 
+/* ACP_SDW Configuration Request - SOF_IPC_DAI_AMD_SDW_CONFIG */
+struct sof_ipc_dai_acp_sdw_params {
+       struct sof_ipc_hdr hdr;
+       u32 rate;
+       u32 channels;
+} __packed;
+
 #endif
index 4773a5f..0764a80 100644 (file)
@@ -89,6 +89,7 @@ enum sof_ipc_dai_type {
        SOF_DAI_AMD_SP_VIRTUAL,         /**< AMD ACP SP VIRTUAL */
        SOF_DAI_AMD_HS_VIRTUAL,         /**< AMD ACP HS VIRTUAL */
        SOF_DAI_IMX_MICFIL,             /** < i.MX MICFIL PDM */
+       SOF_DAI_AMD_SDW,                /**< AMD ACP SDW */
 };
 
 /* general purpose DAI configuration */
@@ -119,6 +120,7 @@ struct sof_ipc_dai_config {
                struct sof_ipc_dai_acp_params acphs;
                struct sof_ipc_dai_mtk_afe_params afe;
                struct sof_ipc_dai_micfil_params micfil;
+               struct sof_ipc_dai_acp_sdw_params acp_sdw;
        };
 } __packed;
 
index ee57089..6bf00c0 100644 (file)
 #define SOF_TKN_IMX_MICFIL_RATE                        2000
 #define SOF_TKN_IMX_MICFIL_CH                  2001
 
+/* ACP SDW */
+#define SOF_TKN_AMD_ACP_SDW_RATE               2100
+#define SOF_TKN_AMD_ACP_SDW_CH                 2101
+
 #endif
index 330f04b..35769dd 100644 (file)
@@ -395,6 +395,31 @@ static int sof_ipc3_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
                dev_dbg(component->dev, "MICFIL PDM channels_min: %d channels_max: %d\n",
                        channels->min, channels->max);
                break;
+       case SOF_DAI_AMD_SDW:
+               /* change the default trigger sequence as per HW implementation */
+               for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_PLAYBACK, dpcm) {
+                       struct snd_soc_pcm_runtime *fe = dpcm->fe;
+
+                       fe->dai_link->trigger[SNDRV_PCM_STREAM_PLAYBACK] =
+                                       SND_SOC_DPCM_TRIGGER_POST;
+               }
+
+               for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_CAPTURE, dpcm) {
+                       struct snd_soc_pcm_runtime *fe = dpcm->fe;
+
+                       fe->dai_link->trigger[SNDRV_PCM_STREAM_CAPTURE] =
+                                       SND_SOC_DPCM_TRIGGER_POST;
+               }
+               rate->min = private->dai_config->acp_sdw.rate;
+               rate->max = private->dai_config->acp_sdw.rate;
+               channels->min = private->dai_config->acp_sdw.channels;
+               channels->max = private->dai_config->acp_sdw.channels;
+
+               dev_dbg(component->dev,
+                       "AMD_SDW rate_min: %d rate_max: %d\n", rate->min, rate->max);
+               dev_dbg(component->dev, "AMD_SDW channels_min: %d channels_max: %d\n",
+                       channels->min, channels->max);
+               break;
        default:
                dev_err(component->dev, "Invalid DAI type %d\n", private->dai_config->type);
                break;
index a8832a1..0970dbd 100644 (file)
@@ -298,6 +298,14 @@ static const struct sof_topology_token micfil_pdm_tokens[] = {
                offsetof(struct sof_ipc_dai_micfil_params, pdm_ch)},
 };
 
+/* ACP_SDW */
+static const struct sof_topology_token acp_sdw_tokens[] = {
+       {SOF_TKN_AMD_ACP_SDW_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
+               offsetof(struct sof_ipc_dai_acp_sdw_params, rate)},
+       {SOF_TKN_AMD_ACP_SDW_CH, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
+               offsetof(struct sof_ipc_dai_acp_sdw_params, channels)},
+};
+
 /* Core tokens */
 static const struct sof_topology_token core_tokens[] = {
        {SOF_TKN_COMP_CORE_ID, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
@@ -336,6 +344,7 @@ static const struct sof_token_info ipc3_token_list[SOF_TOKEN_COUNT] = {
        [SOF_ACPI2S_TOKENS]   = {"ACPI2S tokens", acpi2s_tokens, ARRAY_SIZE(acpi2s_tokens)},
        [SOF_MICFIL_TOKENS] = {"MICFIL PDM tokens",
                micfil_pdm_tokens, ARRAY_SIZE(micfil_pdm_tokens)},
+       [SOF_ACP_SDW_TOKENS]   = {"ACP_SDW tokens", acp_sdw_tokens, ARRAY_SIZE(acp_sdw_tokens)},
 };
 
 /**
@@ -1315,6 +1324,34 @@ static int sof_link_acp_hs_load(struct snd_soc_component *scomp, struct snd_sof_
        return 0;
 }
 
+static int sof_link_acp_sdw_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink,
+                                struct sof_ipc_dai_config *config, struct snd_sof_dai *dai)
+{
+       struct sof_dai_private_data *private = dai->private;
+       u32 size = sizeof(*config);
+       int ret;
+
+       /* parse the required set of ACP_SDW tokens based on num_hw_cfgs */
+       ret = sof_update_ipc_object(scomp, &config->acp_sdw, SOF_ACP_SDW_TOKENS, slink->tuples,
+                                   slink->num_tuples, size, slink->num_hw_configs);
+       if (ret < 0)
+               return ret;
+
+       /* init IPC */
+       config->hdr.size = size;
+       dev_dbg(scomp->dev, "ACP SDW config rate %d channels %d\n",
+               config->acp_sdw.rate, config->acp_sdw.channels);
+
+       /* set config for all DAI's with name matching the link name */
+       dai->number_configs = 1;
+       dai->current_config = 0;
+       private->dai_config = kmemdup(config, size, GFP_KERNEL);
+       if (!private->dai_config)
+               return -ENOMEM;
+
+       return 0;
+}
+
 static int sof_link_afe_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink,
                             struct sof_ipc_dai_config *config, struct snd_sof_dai *dai)
 {
@@ -1629,6 +1666,9 @@ static int sof_ipc3_widget_setup_comp_dai(struct snd_sof_widget *swidget)
                case SOF_DAI_MEDIATEK_AFE:
                        ret = sof_link_afe_load(scomp, slink, config, dai);
                        break;
+               case SOF_DAI_AMD_SDW:
+                       ret = sof_link_acp_sdw_load(scomp, slink, config, dai);
+                       break;
                default:
                        break;
                }
index 8874ee5..f98242a 100644 (file)
@@ -276,6 +276,7 @@ enum sof_tokens {
        SOF_ACPDMIC_TOKENS,
        SOF_ACPI2S_TOKENS,
        SOF_MICFIL_TOKENS,
+       SOF_ACP_SDW_TOKENS,
 
        /* this should be the last */
        SOF_TOKEN_COUNT,
index 617a225..25fb0d1 100644 (file)
@@ -297,6 +297,7 @@ static const struct sof_dai_types sof_dais[] = {
        {"ACPSP_VIRTUAL", SOF_DAI_AMD_SP_VIRTUAL},
        {"ACPHS_VIRTUAL", SOF_DAI_AMD_HS_VIRTUAL},
        {"MICFIL", SOF_DAI_IMX_MICFIL},
+       {"ACP_SDW", SOF_DAI_AMD_SDW},
 
 };
 
@@ -1968,6 +1969,10 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, struct snd_
                token_id = SOF_MICFIL_TOKENS;
                num_tuples += token_list[SOF_MICFIL_TOKENS].count;
                break;
+       case SOF_DAI_AMD_SDW:
+               token_id = SOF_ACP_SDW_TOKENS;
+               num_tuples += token_list[SOF_ACP_SDW_TOKENS].count;
+               break;
        default:
                break;
        }