ASoC: SOF: Add support for configuring PDM interface from topology

Currently we only support configuration for number of channels and
sample rate.

Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Iuliana Prodan <iuliana.prodan@nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
Link: https://lore.kernel.org/r/20231109135900.88310-3-daniel.baluta@oss.nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Daniel Baluta 2023-11-09 15:59:00 +02:00 committed by Mark Brown
parent fc85d9d0b3
commit 89ef42088b
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
7 changed files with 76 additions and 0 deletions

View File

@ -51,4 +51,11 @@ struct sof_ipc_dai_sai_params {
uint16_t tdm_slot_width; uint16_t tdm_slot_width;
uint16_t reserved2; /* alignment */ uint16_t reserved2; /* alignment */
} __packed; } __packed;
/* MICFIL Configuration Request - SOF_IPC_DAI_MICFIL_CONFIG */
struct sof_ipc_dai_micfil_params {
uint32_t pdm_rate;
uint32_t pdm_ch;
} __packed;
#endif #endif

View File

@ -88,6 +88,7 @@ enum sof_ipc_dai_type {
SOF_DAI_AMD_HS, /**< Amd HS */ SOF_DAI_AMD_HS, /**< Amd HS */
SOF_DAI_AMD_SP_VIRTUAL, /**< AMD ACP SP VIRTUAL */ SOF_DAI_AMD_SP_VIRTUAL, /**< AMD ACP SP VIRTUAL */
SOF_DAI_AMD_HS_VIRTUAL, /**< AMD ACP HS VIRTUAL */ SOF_DAI_AMD_HS_VIRTUAL, /**< AMD ACP HS VIRTUAL */
SOF_DAI_IMX_MICFIL, /** < i.MX MICFIL PDM */
}; };
/* general purpose DAI configuration */ /* general purpose DAI configuration */
@ -117,6 +118,7 @@ struct sof_ipc_dai_config {
struct sof_ipc_dai_acpdmic_params acpdmic; struct sof_ipc_dai_acpdmic_params acpdmic;
struct sof_ipc_dai_acp_params acphs; struct sof_ipc_dai_acp_params acphs;
struct sof_ipc_dai_mtk_afe_params afe; struct sof_ipc_dai_mtk_afe_params afe;
struct sof_ipc_dai_micfil_params micfil;
}; };
} __packed; } __packed;

View File

@ -213,4 +213,8 @@
#define SOF_TKN_AMD_ACPI2S_CH 1701 #define SOF_TKN_AMD_ACPI2S_CH 1701
#define SOF_TKN_AMD_ACPI2S_TDM_MODE 1702 #define SOF_TKN_AMD_ACPI2S_TDM_MODE 1702
/* MICFIL PDM */
#define SOF_TKN_IMX_MICFIL_RATE 2000
#define SOF_TKN_IMX_MICFIL_CH 2001
#endif #endif

View File

@ -384,6 +384,17 @@ static int sof_ipc3_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
dev_dbg(component->dev, "AMD_DMIC channels_min: %d channels_max: %d\n", dev_dbg(component->dev, "AMD_DMIC channels_min: %d channels_max: %d\n",
channels->min, channels->max); channels->min, channels->max);
break; break;
case SOF_DAI_IMX_MICFIL:
rate->min = private->dai_config->micfil.pdm_rate;
rate->max = private->dai_config->micfil.pdm_rate;
channels->min = private->dai_config->micfil.pdm_ch;
channels->max = private->dai_config->micfil.pdm_ch;
dev_dbg(component->dev,
"MICFIL PDM rate_min: %d rate_max: %d\n", rate->min, rate->max);
dev_dbg(component->dev, "MICFIL PDM channels_min: %d channels_max: %d\n",
channels->min, channels->max);
break;
default: default:
dev_err(component->dev, "Invalid DAI type %d\n", private->dai_config->type); dev_err(component->dev, "Invalid DAI type %d\n", private->dai_config->type);
break; break;

View File

@ -286,6 +286,16 @@ static const struct sof_topology_token acpi2s_tokens[] = {
offsetof(struct sof_ipc_dai_acp_params, tdm_mode)}, offsetof(struct sof_ipc_dai_acp_params, tdm_mode)},
}; };
/* MICFIL PDM */
static const struct sof_topology_token micfil_pdm_tokens[] = {
{SOF_TKN_IMX_MICFIL_RATE,
SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
offsetof(struct sof_ipc_dai_micfil_params, pdm_rate)},
{SOF_TKN_IMX_MICFIL_CH,
SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
offsetof(struct sof_ipc_dai_micfil_params, pdm_ch)},
};
/* Core tokens */ /* Core tokens */
static const struct sof_topology_token core_tokens[] = { static const struct sof_topology_token core_tokens[] = {
{SOF_TKN_COMP_CORE_ID, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, {SOF_TKN_COMP_CORE_ID, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
@ -322,6 +332,8 @@ static const struct sof_token_info ipc3_token_list[SOF_TOKEN_COUNT] = {
[SOF_AFE_TOKENS] = {"AFE tokens", afe_tokens, ARRAY_SIZE(afe_tokens)}, [SOF_AFE_TOKENS] = {"AFE tokens", afe_tokens, ARRAY_SIZE(afe_tokens)},
[SOF_ACPDMIC_TOKENS] = {"ACPDMIC tokens", acpdmic_tokens, ARRAY_SIZE(acpdmic_tokens)}, [SOF_ACPDMIC_TOKENS] = {"ACPDMIC tokens", acpdmic_tokens, ARRAY_SIZE(acpdmic_tokens)},
[SOF_ACPI2S_TOKENS] = {"ACPI2S tokens", acpi2s_tokens, ARRAY_SIZE(acpi2s_tokens)}, [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)},
}; };
/** /**
@ -1136,6 +1148,37 @@ static int sof_link_esai_load(struct snd_soc_component *scomp, struct snd_sof_da
return 0; return 0;
} }
static int sof_link_micfil_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink,
struct sof_ipc_dai_config *config, struct snd_sof_dai *dai)
{
struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs;
struct sof_dai_private_data *private = dai->private;
u32 size = sizeof(*config);
int ret;
/* handle master/slave and inverted clocks */
sof_dai_set_format(hw_config, config);
config->hdr.size = size;
/* parse the required set of MICFIL PDM tokens based on num_hw_cfgs */
ret = sof_update_ipc_object(scomp, &config->micfil, SOF_MICFIL_TOKENS, slink->tuples,
slink->num_tuples, size, slink->num_hw_configs);
if (ret < 0)
return ret;
dev_info(scomp->dev, "MICFIL PDM config dai_index %d channel %d rate %d\n",
config->dai_index, config->micfil.pdm_ch, config->micfil.pdm_rate);
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_acp_dmic_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, static int sof_link_acp_dmic_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_ipc_dai_config *config, struct snd_sof_dai *dai)
{ {
@ -1559,6 +1602,9 @@ static int sof_ipc3_widget_setup_comp_dai(struct snd_sof_widget *swidget)
case SOF_DAI_IMX_ESAI: case SOF_DAI_IMX_ESAI:
ret = sof_link_esai_load(scomp, slink, config, dai); ret = sof_link_esai_load(scomp, slink, config, dai);
break; break;
case SOF_DAI_IMX_MICFIL:
ret = sof_link_micfil_load(scomp, slink, config, dai);
break;
case SOF_DAI_AMD_BT: case SOF_DAI_AMD_BT:
ret = sof_link_acp_bt_load(scomp, slink, config, dai); ret = sof_link_acp_bt_load(scomp, slink, config, dai);
break; break;

View File

@ -275,6 +275,7 @@ enum sof_tokens {
SOF_GAIN_TOKENS, SOF_GAIN_TOKENS,
SOF_ACPDMIC_TOKENS, SOF_ACPDMIC_TOKENS,
SOF_ACPI2S_TOKENS, SOF_ACPI2S_TOKENS,
SOF_MICFIL_TOKENS,
/* this should be the last */ /* this should be the last */
SOF_TOKEN_COUNT, SOF_TOKEN_COUNT,

View File

@ -296,6 +296,7 @@ static const struct sof_dai_types sof_dais[] = {
{"AFE", SOF_DAI_MEDIATEK_AFE}, {"AFE", SOF_DAI_MEDIATEK_AFE},
{"ACPSP_VIRTUAL", SOF_DAI_AMD_SP_VIRTUAL}, {"ACPSP_VIRTUAL", SOF_DAI_AMD_SP_VIRTUAL},
{"ACPHS_VIRTUAL", SOF_DAI_AMD_HS_VIRTUAL}, {"ACPHS_VIRTUAL", SOF_DAI_AMD_HS_VIRTUAL},
{"MICFIL", SOF_DAI_IMX_MICFIL},
}; };
@ -1960,6 +1961,10 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, struct snd_
token_id = SOF_ACPI2S_TOKENS; token_id = SOF_ACPI2S_TOKENS;
num_tuples += token_list[SOF_ACPI2S_TOKENS].count; num_tuples += token_list[SOF_ACPI2S_TOKENS].count;
break; break;
case SOF_DAI_IMX_MICFIL:
token_id = SOF_MICFIL_TOKENS;
num_tuples += token_list[SOF_MICFIL_TOKENS].count;
break;
default: default:
break; break;
} }