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

ASoC: SOF: topology: Add support for AMD ACP DAIs

Add new sof dais and config to pass topology file configuration
to SOF firmware running on ACP's DSP core. ACP firmware support
I2S_BT, I2S_SP and DMIC controller hence add three new dais to
the list of supported sof_dais

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
Reviewed-by: Bard Liao <bard.liao@intel.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
Link: https://lore.kernel.org/r/20211117093734.17407-12-daniel.baluta@oss.nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Ajit Kumar Pandey and committed by
Mark Brown
efb931cd 63fba90f

+173
+21
include/sound/sof/dai-amd.h
··· 1 + /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ 2 + /* 3 + * This file is provided under a dual BSD/GPLv2 license. When using or 4 + * redistributing this file, you may do so under either license. 5 + * 6 + * Copyright(c) 2021 Advanced Micro Devices, Inc.. All rights reserved. 7 + */ 8 + 9 + #ifndef __INCLUDE_SOUND_SOF_DAI_AMD_H__ 10 + #define __INCLUDE_SOUND_SOF_DAI_AMD_H__ 11 + 12 + #include <sound/sof/header.h> 13 + 14 + /* ACP Configuration Request - SOF_IPC_DAI_AMD_CONFIG */ 15 + struct sof_ipc_dai_acp_params { 16 + struct sof_ipc_hdr hdr; 17 + 18 + uint32_t fsync_rate; /* FSYNC frequency in Hz */ 19 + uint32_t tdm_slots; 20 + } __packed; 21 + #endif
+7
include/sound/sof/dai.h
··· 12 12 #include <sound/sof/header.h> 13 13 #include <sound/sof/dai-intel.h> 14 14 #include <sound/sof/dai-imx.h> 15 + #include <sound/sof/dai-amd.h> 15 16 16 17 /* 17 18 * DAI Configuration. ··· 67 66 SOF_DAI_INTEL_ALH, /**< Intel ALH */ 68 67 SOF_DAI_IMX_SAI, /**< i.MX SAI */ 69 68 SOF_DAI_IMX_ESAI, /**< i.MX ESAI */ 69 + SOF_DAI_AMD_BT, /**< AMD ACP BT*/ 70 + SOF_DAI_AMD_SP, /**< AMD ACP SP */ 71 + SOF_DAI_AMD_DMIC, /**< AMD ACP DMIC */ 70 72 }; 71 73 72 74 /* general purpose DAI configuration */ ··· 94 90 struct sof_ipc_dai_alh_params alh; 95 91 struct sof_ipc_dai_esai_params esai; 96 92 struct sof_ipc_dai_sai_params sai; 93 + struct sof_ipc_dai_acp_params acpbt; 94 + struct sof_ipc_dai_acp_params acpsp; 95 + struct sof_ipc_dai_acp_params acpdmic; 97 96 }; 98 97 } __packed; 99 98
+36
sound/soc/sof/pcm.c
··· 826 826 "channels_min: %d channels_max: %d\n", 827 827 channels->min, channels->max); 828 828 break; 829 + case SOF_DAI_AMD_BT: 830 + rate->min = dai->dai_config->acpbt.fsync_rate; 831 + rate->max = dai->dai_config->acpbt.fsync_rate; 832 + channels->min = dai->dai_config->acpbt.tdm_slots; 833 + channels->max = dai->dai_config->acpbt.tdm_slots; 834 + 835 + dev_dbg(component->dev, 836 + "AMD_BT rate_min: %d rate_max: %d\n", rate->min, rate->max); 837 + dev_dbg(component->dev, 838 + "AMD_BT channels_min: %d channels_max: %d\n", 839 + channels->min, channels->max); 840 + break; 841 + case SOF_DAI_AMD_SP: 842 + rate->min = dai->dai_config->acpsp.fsync_rate; 843 + rate->max = dai->dai_config->acpsp.fsync_rate; 844 + channels->min = dai->dai_config->acpsp.tdm_slots; 845 + channels->max = dai->dai_config->acpsp.tdm_slots; 846 + 847 + dev_dbg(component->dev, 848 + "AMD_SP rate_min: %d rate_max: %d\n", rate->min, rate->max); 849 + dev_dbg(component->dev, 850 + "AMD_SP channels_min: %d channels_max: %d\n", 851 + channels->min, channels->max); 852 + break; 853 + case SOF_DAI_AMD_DMIC: 854 + rate->min = dai->dai_config->acpdmic.fsync_rate; 855 + rate->max = dai->dai_config->acpdmic.fsync_rate; 856 + channels->min = dai->dai_config->acpdmic.tdm_slots; 857 + channels->max = dai->dai_config->acpdmic.tdm_slots; 858 + 859 + dev_dbg(component->dev, 860 + "AMD_DMIC rate_min: %d rate_max: %d\n", rate->min, rate->max); 861 + dev_dbg(component->dev, 862 + "AMD_DMIC channels_min: %d channels_max: %d\n", 863 + channels->min, channels->max); 864 + break; 829 865 default: 830 866 dev_err(component->dev, "error: invalid DAI type %d\n", 831 867 dai->dai_config->type);
+109
sound/soc/sof/topology.c
··· 376 376 {"ALH", SOF_DAI_INTEL_ALH}, 377 377 {"SAI", SOF_DAI_IMX_SAI}, 378 378 {"ESAI", SOF_DAI_IMX_ESAI}, 379 + {"ACP", SOF_DAI_AMD_BT}, 380 + {"ACPSP", SOF_DAI_AMD_SP}, 381 + {"ACPDMIC", SOF_DAI_AMD_DMIC}, 379 382 }; 380 383 381 384 static enum sof_ipc_dai_type find_dai(const char *name) ··· 2995 2992 return ret; 2996 2993 } 2997 2994 2995 + static int sof_link_acp_dmic_load(struct snd_soc_component *scomp, int index, 2996 + struct snd_soc_dai_link *link, 2997 + struct snd_soc_tplg_link_config *cfg, 2998 + struct snd_soc_tplg_hw_config *hw_config, 2999 + struct sof_ipc_dai_config *config) 3000 + { 3001 + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 3002 + u32 size = sizeof(*config); 3003 + int ret; 3004 + 3005 + /* handle master/slave and inverted clocks */ 3006 + sof_dai_set_format(hw_config, config); 3007 + 3008 + /* init IPC */ 3009 + memset(&config->acpdmic, 0, sizeof(struct sof_ipc_dai_acp_params)); 3010 + config->hdr.size = size; 3011 + 3012 + config->acpdmic.fsync_rate = le32_to_cpu(hw_config->fsync_rate); 3013 + config->acpdmic.tdm_slots = le32_to_cpu(hw_config->tdm_slots); 3014 + 3015 + dev_info(scomp->dev, "ACP_DMIC config ACP%d channel %d rate %d\n", 3016 + config->dai_index, config->acpdmic.tdm_slots, 3017 + config->acpdmic.fsync_rate); 3018 + 3019 + /* set config for all DAI's with name matching the link name */ 3020 + ret = sof_set_dai_config(sdev, size, link, config); 3021 + if (ret < 0) 3022 + dev_err(scomp->dev, "ACP_DMIC failed to save DAI config for ACP%d\n", 3023 + config->dai_index); 3024 + return ret; 3025 + } 3026 + 3027 + static int sof_link_acp_bt_load(struct snd_soc_component *scomp, int index, 3028 + struct snd_soc_dai_link *link, 3029 + struct snd_soc_tplg_link_config *cfg, 3030 + struct snd_soc_tplg_hw_config *hw_config, 3031 + struct sof_ipc_dai_config *config) 3032 + { 3033 + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 3034 + u32 size = sizeof(*config); 3035 + int ret; 3036 + 3037 + /* handle master/slave and inverted clocks */ 3038 + sof_dai_set_format(hw_config, config); 3039 + 3040 + /* init IPC */ 3041 + memset(&config->acpbt, 0, sizeof(struct sof_ipc_dai_acp_params)); 3042 + config->hdr.size = size; 3043 + 3044 + config->acpbt.fsync_rate = le32_to_cpu(hw_config->fsync_rate); 3045 + config->acpbt.tdm_slots = le32_to_cpu(hw_config->tdm_slots); 3046 + 3047 + dev_info(scomp->dev, "ACP_BT config ACP%d channel %d rate %d\n", 3048 + config->dai_index, config->acpbt.tdm_slots, 3049 + config->acpbt.fsync_rate); 3050 + 3051 + /* set config for all DAI's with name matching the link name */ 3052 + ret = sof_set_dai_config(sdev, size, link, config); 3053 + if (ret < 0) 3054 + dev_err(scomp->dev, "ACP_BT failed to save DAI config for ACP%d\n", 3055 + config->dai_index); 3056 + return ret; 3057 + } 3058 + 3059 + static int sof_link_acp_sp_load(struct snd_soc_component *scomp, int index, 3060 + struct snd_soc_dai_link *link, 3061 + struct snd_soc_tplg_link_config *cfg, 3062 + struct snd_soc_tplg_hw_config *hw_config, 3063 + struct sof_ipc_dai_config *config) 3064 + { 3065 + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 3066 + u32 size = sizeof(*config); 3067 + int ret; 3068 + 3069 + /* handle master/slave and inverted clocks */ 3070 + sof_dai_set_format(hw_config, config); 3071 + 3072 + /* init IPC */ 3073 + memset(&config->acpsp, 0, sizeof(struct sof_ipc_dai_acp_params)); 3074 + config->hdr.size = size; 3075 + 3076 + config->acpsp.fsync_rate = le32_to_cpu(hw_config->fsync_rate); 3077 + config->acpsp.tdm_slots = le32_to_cpu(hw_config->tdm_slots); 3078 + 3079 + dev_info(scomp->dev, "ACP_SP config ACP%d channel %d rate %d\n", 3080 + config->dai_index, config->acpsp.tdm_slots, 3081 + config->acpsp.fsync_rate); 3082 + 3083 + /* set config for all DAI's with name matching the link name */ 3084 + ret = sof_set_dai_config(sdev, size, link, config); 3085 + if (ret < 0) 3086 + dev_err(scomp->dev, "ACP_SP failed to save DAI config for ACP%d\n", 3087 + config->dai_index); 3088 + return ret; 3089 + } 3090 + 2998 3091 static int sof_link_dmic_load(struct snd_soc_component *scomp, int index, 2999 3092 struct snd_soc_dai_link *link, 3000 3093 struct snd_soc_tplg_link_config *cfg, ··· 3375 3276 break; 3376 3277 case SOF_DAI_IMX_ESAI: 3377 3278 ret = sof_link_esai_load(scomp, index, link, cfg, hw_config + curr_conf, config); 3279 + break; 3280 + case SOF_DAI_AMD_BT: 3281 + ret = sof_link_acp_bt_load(scomp, index, link, cfg, hw_config + curr_conf, config); 3282 + break; 3283 + case SOF_DAI_AMD_SP: 3284 + ret = sof_link_acp_sp_load(scomp, index, link, cfg, hw_config + curr_conf, config); 3285 + break; 3286 + case SOF_DAI_AMD_DMIC: 3287 + ret = sof_link_acp_dmic_load(scomp, index, link, cfg, hw_config + curr_conf, 3288 + config); 3378 3289 break; 3379 3290 default: 3380 3291 dev_err(scomp->dev, "error: invalid DAI type %d\n", common_config.type);