Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Daniel Baluta and committed by
Mark Brown
89ef4208 fc85d9d0

+76
+7
include/sound/sof/dai-imx.h
··· 51 51 uint16_t tdm_slot_width; 52 52 uint16_t reserved2; /* alignment */ 53 53 } __packed; 54 + 55 + /* MICFIL Configuration Request - SOF_IPC_DAI_MICFIL_CONFIG */ 56 + struct sof_ipc_dai_micfil_params { 57 + uint32_t pdm_rate; 58 + uint32_t pdm_ch; 59 + } __packed; 60 + 54 61 #endif
+2
include/sound/sof/dai.h
··· 88 88 SOF_DAI_AMD_HS, /**< Amd HS */ 89 89 SOF_DAI_AMD_SP_VIRTUAL, /**< AMD ACP SP VIRTUAL */ 90 90 SOF_DAI_AMD_HS_VIRTUAL, /**< AMD ACP HS VIRTUAL */ 91 + SOF_DAI_IMX_MICFIL, /** < i.MX MICFIL PDM */ 91 92 }; 92 93 93 94 /* general purpose DAI configuration */ ··· 118 117 struct sof_ipc_dai_acpdmic_params acpdmic; 119 118 struct sof_ipc_dai_acp_params acphs; 120 119 struct sof_ipc_dai_mtk_afe_params afe; 120 + struct sof_ipc_dai_micfil_params micfil; 121 121 }; 122 122 } __packed; 123 123
+4
include/uapi/sound/sof/tokens.h
··· 213 213 #define SOF_TKN_AMD_ACPI2S_CH 1701 214 214 #define SOF_TKN_AMD_ACPI2S_TDM_MODE 1702 215 215 216 + /* MICFIL PDM */ 217 + #define SOF_TKN_IMX_MICFIL_RATE 2000 218 + #define SOF_TKN_IMX_MICFIL_CH 2001 219 + 216 220 #endif
+11
sound/soc/sof/ipc3-pcm.c
··· 384 384 dev_dbg(component->dev, "AMD_DMIC channels_min: %d channels_max: %d\n", 385 385 channels->min, channels->max); 386 386 break; 387 + case SOF_DAI_IMX_MICFIL: 388 + rate->min = private->dai_config->micfil.pdm_rate; 389 + rate->max = private->dai_config->micfil.pdm_rate; 390 + channels->min = private->dai_config->micfil.pdm_ch; 391 + channels->max = private->dai_config->micfil.pdm_ch; 392 + 393 + dev_dbg(component->dev, 394 + "MICFIL PDM rate_min: %d rate_max: %d\n", rate->min, rate->max); 395 + dev_dbg(component->dev, "MICFIL PDM channels_min: %d channels_max: %d\n", 396 + channels->min, channels->max); 397 + break; 387 398 default: 388 399 dev_err(component->dev, "Invalid DAI type %d\n", private->dai_config->type); 389 400 break;
+46
sound/soc/sof/ipc3-topology.c
··· 286 286 offsetof(struct sof_ipc_dai_acp_params, tdm_mode)}, 287 287 }; 288 288 289 + /* MICFIL PDM */ 290 + static const struct sof_topology_token micfil_pdm_tokens[] = { 291 + {SOF_TKN_IMX_MICFIL_RATE, 292 + SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 293 + offsetof(struct sof_ipc_dai_micfil_params, pdm_rate)}, 294 + {SOF_TKN_IMX_MICFIL_CH, 295 + SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 296 + offsetof(struct sof_ipc_dai_micfil_params, pdm_ch)}, 297 + }; 298 + 289 299 /* Core tokens */ 290 300 static const struct sof_topology_token core_tokens[] = { 291 301 {SOF_TKN_COMP_CORE_ID, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, ··· 332 322 [SOF_AFE_TOKENS] = {"AFE tokens", afe_tokens, ARRAY_SIZE(afe_tokens)}, 333 323 [SOF_ACPDMIC_TOKENS] = {"ACPDMIC tokens", acpdmic_tokens, ARRAY_SIZE(acpdmic_tokens)}, 334 324 [SOF_ACPI2S_TOKENS] = {"ACPI2S tokens", acpi2s_tokens, ARRAY_SIZE(acpi2s_tokens)}, 325 + [SOF_MICFIL_TOKENS] = {"MICFIL PDM tokens", 326 + micfil_pdm_tokens, ARRAY_SIZE(micfil_pdm_tokens)}, 335 327 }; 336 328 337 329 /** ··· 1148 1136 return 0; 1149 1137 } 1150 1138 1139 + static int sof_link_micfil_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1140 + struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1141 + { 1142 + struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs; 1143 + struct sof_dai_private_data *private = dai->private; 1144 + u32 size = sizeof(*config); 1145 + int ret; 1146 + 1147 + /* handle master/slave and inverted clocks */ 1148 + sof_dai_set_format(hw_config, config); 1149 + 1150 + config->hdr.size = size; 1151 + 1152 + /* parse the required set of MICFIL PDM tokens based on num_hw_cfgs */ 1153 + ret = sof_update_ipc_object(scomp, &config->micfil, SOF_MICFIL_TOKENS, slink->tuples, 1154 + slink->num_tuples, size, slink->num_hw_configs); 1155 + if (ret < 0) 1156 + return ret; 1157 + 1158 + dev_info(scomp->dev, "MICFIL PDM config dai_index %d channel %d rate %d\n", 1159 + config->dai_index, config->micfil.pdm_ch, config->micfil.pdm_rate); 1160 + 1161 + dai->number_configs = 1; 1162 + dai->current_config = 0; 1163 + private->dai_config = kmemdup(config, size, GFP_KERNEL); 1164 + if (!private->dai_config) 1165 + return -ENOMEM; 1166 + 1167 + return 0; 1168 + } 1169 + 1151 1170 static int sof_link_acp_dmic_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, 1152 1171 struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) 1153 1172 { ··· 1601 1558 break; 1602 1559 case SOF_DAI_IMX_ESAI: 1603 1560 ret = sof_link_esai_load(scomp, slink, config, dai); 1561 + break; 1562 + case SOF_DAI_IMX_MICFIL: 1563 + ret = sof_link_micfil_load(scomp, slink, config, dai); 1604 1564 break; 1605 1565 case SOF_DAI_AMD_BT: 1606 1566 ret = sof_link_acp_bt_load(scomp, slink, config, dai);
+1
sound/soc/sof/sof-audio.h
··· 275 275 SOF_GAIN_TOKENS, 276 276 SOF_ACPDMIC_TOKENS, 277 277 SOF_ACPI2S_TOKENS, 278 + SOF_MICFIL_TOKENS, 278 279 279 280 /* this should be the last */ 280 281 SOF_TOKEN_COUNT,
+5
sound/soc/sof/topology.c
··· 296 296 {"AFE", SOF_DAI_MEDIATEK_AFE}, 297 297 {"ACPSP_VIRTUAL", SOF_DAI_AMD_SP_VIRTUAL}, 298 298 {"ACPHS_VIRTUAL", SOF_DAI_AMD_HS_VIRTUAL}, 299 + {"MICFIL", SOF_DAI_IMX_MICFIL}, 299 300 300 301 }; 301 302 ··· 1960 1959 case SOF_DAI_AMD_HS_VIRTUAL: 1961 1960 token_id = SOF_ACPI2S_TOKENS; 1962 1961 num_tuples += token_list[SOF_ACPI2S_TOKENS].count; 1962 + break; 1963 + case SOF_DAI_IMX_MICFIL: 1964 + token_id = SOF_MICFIL_TOKENS; 1965 + num_tuples += token_list[SOF_MICFIL_TOKENS].count; 1963 1966 break; 1964 1967 default: 1965 1968 break;