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>
This commit is contained in:
committed by
Mark Brown
parent
63fba90fc8
commit
efb931cdc4
21
include/sound/sof/dai-amd.h
Normal file
21
include/sound/sof/dai-amd.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
|
||||||
|
/*
|
||||||
|
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||||
|
* redistributing this file, you may do so under either license.
|
||||||
|
*
|
||||||
|
* Copyright(c) 2021 Advanced Micro Devices, Inc.. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __INCLUDE_SOUND_SOF_DAI_AMD_H__
|
||||||
|
#define __INCLUDE_SOUND_SOF_DAI_AMD_H__
|
||||||
|
|
||||||
|
#include <sound/sof/header.h>
|
||||||
|
|
||||||
|
/* ACP Configuration Request - SOF_IPC_DAI_AMD_CONFIG */
|
||||||
|
struct sof_ipc_dai_acp_params {
|
||||||
|
struct sof_ipc_hdr hdr;
|
||||||
|
|
||||||
|
uint32_t fsync_rate; /* FSYNC frequency in Hz */
|
||||||
|
uint32_t tdm_slots;
|
||||||
|
} __packed;
|
||||||
|
#endif
|
@ -12,6 +12,7 @@
|
|||||||
#include <sound/sof/header.h>
|
#include <sound/sof/header.h>
|
||||||
#include <sound/sof/dai-intel.h>
|
#include <sound/sof/dai-intel.h>
|
||||||
#include <sound/sof/dai-imx.h>
|
#include <sound/sof/dai-imx.h>
|
||||||
|
#include <sound/sof/dai-amd.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DAI Configuration.
|
* DAI Configuration.
|
||||||
@ -66,6 +67,9 @@ enum sof_ipc_dai_type {
|
|||||||
SOF_DAI_INTEL_ALH, /**< Intel ALH */
|
SOF_DAI_INTEL_ALH, /**< Intel ALH */
|
||||||
SOF_DAI_IMX_SAI, /**< i.MX SAI */
|
SOF_DAI_IMX_SAI, /**< i.MX SAI */
|
||||||
SOF_DAI_IMX_ESAI, /**< i.MX ESAI */
|
SOF_DAI_IMX_ESAI, /**< i.MX ESAI */
|
||||||
|
SOF_DAI_AMD_BT, /**< AMD ACP BT*/
|
||||||
|
SOF_DAI_AMD_SP, /**< AMD ACP SP */
|
||||||
|
SOF_DAI_AMD_DMIC, /**< AMD ACP DMIC */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* general purpose DAI configuration */
|
/* general purpose DAI configuration */
|
||||||
@ -90,6 +94,9 @@ struct sof_ipc_dai_config {
|
|||||||
struct sof_ipc_dai_alh_params alh;
|
struct sof_ipc_dai_alh_params alh;
|
||||||
struct sof_ipc_dai_esai_params esai;
|
struct sof_ipc_dai_esai_params esai;
|
||||||
struct sof_ipc_dai_sai_params sai;
|
struct sof_ipc_dai_sai_params sai;
|
||||||
|
struct sof_ipc_dai_acp_params acpbt;
|
||||||
|
struct sof_ipc_dai_acp_params acpsp;
|
||||||
|
struct sof_ipc_dai_acp_params acpdmic;
|
||||||
};
|
};
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
@ -826,6 +826,42 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa
|
|||||||
"channels_min: %d channels_max: %d\n",
|
"channels_min: %d channels_max: %d\n",
|
||||||
channels->min, channels->max);
|
channels->min, channels->max);
|
||||||
break;
|
break;
|
||||||
|
case SOF_DAI_AMD_BT:
|
||||||
|
rate->min = dai->dai_config->acpbt.fsync_rate;
|
||||||
|
rate->max = dai->dai_config->acpbt.fsync_rate;
|
||||||
|
channels->min = dai->dai_config->acpbt.tdm_slots;
|
||||||
|
channels->max = dai->dai_config->acpbt.tdm_slots;
|
||||||
|
|
||||||
|
dev_dbg(component->dev,
|
||||||
|
"AMD_BT rate_min: %d rate_max: %d\n", rate->min, rate->max);
|
||||||
|
dev_dbg(component->dev,
|
||||||
|
"AMD_BT channels_min: %d channels_max: %d\n",
|
||||||
|
channels->min, channels->max);
|
||||||
|
break;
|
||||||
|
case SOF_DAI_AMD_SP:
|
||||||
|
rate->min = dai->dai_config->acpsp.fsync_rate;
|
||||||
|
rate->max = dai->dai_config->acpsp.fsync_rate;
|
||||||
|
channels->min = dai->dai_config->acpsp.tdm_slots;
|
||||||
|
channels->max = dai->dai_config->acpsp.tdm_slots;
|
||||||
|
|
||||||
|
dev_dbg(component->dev,
|
||||||
|
"AMD_SP rate_min: %d rate_max: %d\n", rate->min, rate->max);
|
||||||
|
dev_dbg(component->dev,
|
||||||
|
"AMD_SP channels_min: %d channels_max: %d\n",
|
||||||
|
channels->min, channels->max);
|
||||||
|
break;
|
||||||
|
case SOF_DAI_AMD_DMIC:
|
||||||
|
rate->min = dai->dai_config->acpdmic.fsync_rate;
|
||||||
|
rate->max = dai->dai_config->acpdmic.fsync_rate;
|
||||||
|
channels->min = dai->dai_config->acpdmic.tdm_slots;
|
||||||
|
channels->max = dai->dai_config->acpdmic.tdm_slots;
|
||||||
|
|
||||||
|
dev_dbg(component->dev,
|
||||||
|
"AMD_DMIC rate_min: %d rate_max: %d\n", rate->min, rate->max);
|
||||||
|
dev_dbg(component->dev,
|
||||||
|
"AMD_DMIC channels_min: %d channels_max: %d\n",
|
||||||
|
channels->min, channels->max);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(component->dev, "error: invalid DAI type %d\n",
|
dev_err(component->dev, "error: invalid DAI type %d\n",
|
||||||
dai->dai_config->type);
|
dai->dai_config->type);
|
||||||
|
@ -376,6 +376,9 @@ static const struct sof_dai_types sof_dais[] = {
|
|||||||
{"ALH", SOF_DAI_INTEL_ALH},
|
{"ALH", SOF_DAI_INTEL_ALH},
|
||||||
{"SAI", SOF_DAI_IMX_SAI},
|
{"SAI", SOF_DAI_IMX_SAI},
|
||||||
{"ESAI", SOF_DAI_IMX_ESAI},
|
{"ESAI", SOF_DAI_IMX_ESAI},
|
||||||
|
{"ACP", SOF_DAI_AMD_BT},
|
||||||
|
{"ACPSP", SOF_DAI_AMD_SP},
|
||||||
|
{"ACPDMIC", SOF_DAI_AMD_DMIC},
|
||||||
};
|
};
|
||||||
|
|
||||||
static enum sof_ipc_dai_type find_dai(const char *name)
|
static enum sof_ipc_dai_type find_dai(const char *name)
|
||||||
@ -2992,6 +2995,102 @@ static int sof_link_esai_load(struct snd_soc_component *scomp, int index,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sof_link_acp_dmic_load(struct snd_soc_component *scomp, int index,
|
||||||
|
struct snd_soc_dai_link *link,
|
||||||
|
struct snd_soc_tplg_link_config *cfg,
|
||||||
|
struct snd_soc_tplg_hw_config *hw_config,
|
||||||
|
struct sof_ipc_dai_config *config)
|
||||||
|
{
|
||||||
|
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
|
||||||
|
u32 size = sizeof(*config);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* handle master/slave and inverted clocks */
|
||||||
|
sof_dai_set_format(hw_config, config);
|
||||||
|
|
||||||
|
/* init IPC */
|
||||||
|
memset(&config->acpdmic, 0, sizeof(struct sof_ipc_dai_acp_params));
|
||||||
|
config->hdr.size = size;
|
||||||
|
|
||||||
|
config->acpdmic.fsync_rate = le32_to_cpu(hw_config->fsync_rate);
|
||||||
|
config->acpdmic.tdm_slots = le32_to_cpu(hw_config->tdm_slots);
|
||||||
|
|
||||||
|
dev_info(scomp->dev, "ACP_DMIC config ACP%d channel %d rate %d\n",
|
||||||
|
config->dai_index, config->acpdmic.tdm_slots,
|
||||||
|
config->acpdmic.fsync_rate);
|
||||||
|
|
||||||
|
/* set config for all DAI's with name matching the link name */
|
||||||
|
ret = sof_set_dai_config(sdev, size, link, config);
|
||||||
|
if (ret < 0)
|
||||||
|
dev_err(scomp->dev, "ACP_DMIC failed to save DAI config for ACP%d\n",
|
||||||
|
config->dai_index);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sof_link_acp_bt_load(struct snd_soc_component *scomp, int index,
|
||||||
|
struct snd_soc_dai_link *link,
|
||||||
|
struct snd_soc_tplg_link_config *cfg,
|
||||||
|
struct snd_soc_tplg_hw_config *hw_config,
|
||||||
|
struct sof_ipc_dai_config *config)
|
||||||
|
{
|
||||||
|
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
|
||||||
|
u32 size = sizeof(*config);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* handle master/slave and inverted clocks */
|
||||||
|
sof_dai_set_format(hw_config, config);
|
||||||
|
|
||||||
|
/* init IPC */
|
||||||
|
memset(&config->acpbt, 0, sizeof(struct sof_ipc_dai_acp_params));
|
||||||
|
config->hdr.size = size;
|
||||||
|
|
||||||
|
config->acpbt.fsync_rate = le32_to_cpu(hw_config->fsync_rate);
|
||||||
|
config->acpbt.tdm_slots = le32_to_cpu(hw_config->tdm_slots);
|
||||||
|
|
||||||
|
dev_info(scomp->dev, "ACP_BT config ACP%d channel %d rate %d\n",
|
||||||
|
config->dai_index, config->acpbt.tdm_slots,
|
||||||
|
config->acpbt.fsync_rate);
|
||||||
|
|
||||||
|
/* set config for all DAI's with name matching the link name */
|
||||||
|
ret = sof_set_dai_config(sdev, size, link, config);
|
||||||
|
if (ret < 0)
|
||||||
|
dev_err(scomp->dev, "ACP_BT failed to save DAI config for ACP%d\n",
|
||||||
|
config->dai_index);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sof_link_acp_sp_load(struct snd_soc_component *scomp, int index,
|
||||||
|
struct snd_soc_dai_link *link,
|
||||||
|
struct snd_soc_tplg_link_config *cfg,
|
||||||
|
struct snd_soc_tplg_hw_config *hw_config,
|
||||||
|
struct sof_ipc_dai_config *config)
|
||||||
|
{
|
||||||
|
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
|
||||||
|
u32 size = sizeof(*config);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* handle master/slave and inverted clocks */
|
||||||
|
sof_dai_set_format(hw_config, config);
|
||||||
|
|
||||||
|
/* init IPC */
|
||||||
|
memset(&config->acpsp, 0, sizeof(struct sof_ipc_dai_acp_params));
|
||||||
|
config->hdr.size = size;
|
||||||
|
|
||||||
|
config->acpsp.fsync_rate = le32_to_cpu(hw_config->fsync_rate);
|
||||||
|
config->acpsp.tdm_slots = le32_to_cpu(hw_config->tdm_slots);
|
||||||
|
|
||||||
|
dev_info(scomp->dev, "ACP_SP config ACP%d channel %d rate %d\n",
|
||||||
|
config->dai_index, config->acpsp.tdm_slots,
|
||||||
|
config->acpsp.fsync_rate);
|
||||||
|
|
||||||
|
/* set config for all DAI's with name matching the link name */
|
||||||
|
ret = sof_set_dai_config(sdev, size, link, config);
|
||||||
|
if (ret < 0)
|
||||||
|
dev_err(scomp->dev, "ACP_SP failed to save DAI config for ACP%d\n",
|
||||||
|
config->dai_index);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int sof_link_dmic_load(struct snd_soc_component *scomp, int index,
|
static int sof_link_dmic_load(struct snd_soc_component *scomp, int index,
|
||||||
struct snd_soc_dai_link *link,
|
struct snd_soc_dai_link *link,
|
||||||
struct snd_soc_tplg_link_config *cfg,
|
struct snd_soc_tplg_link_config *cfg,
|
||||||
@ -3277,6 +3376,16 @@ static int sof_link_load(struct snd_soc_component *scomp, int index,
|
|||||||
case SOF_DAI_IMX_ESAI:
|
case SOF_DAI_IMX_ESAI:
|
||||||
ret = sof_link_esai_load(scomp, index, link, cfg, hw_config + curr_conf, config);
|
ret = sof_link_esai_load(scomp, index, link, cfg, hw_config + curr_conf, config);
|
||||||
break;
|
break;
|
||||||
|
case SOF_DAI_AMD_BT:
|
||||||
|
ret = sof_link_acp_bt_load(scomp, index, link, cfg, hw_config + curr_conf, config);
|
||||||
|
break;
|
||||||
|
case SOF_DAI_AMD_SP:
|
||||||
|
ret = sof_link_acp_sp_load(scomp, index, link, cfg, hw_config + curr_conf, config);
|
||||||
|
break;
|
||||||
|
case SOF_DAI_AMD_DMIC:
|
||||||
|
ret = sof_link_acp_dmic_load(scomp, index, link, cfg, hw_config + curr_conf,
|
||||||
|
config);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(scomp->dev, "error: invalid DAI type %d\n", common_config.type);
|
dev_err(scomp->dev, "error: invalid DAI type %d\n", common_config.type);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
Reference in New Issue
Block a user