Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DNM] dai: add support for Intel UAOL DAI #9227

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 63 additions & 1 deletion src/audio/base_fw_intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@

#include <sof/lib/memory.h>

#if CONFIG_UAOL_INTEL_ADSP
#include <zephyr/drivers/uaol.h>
#endif

#include <ipc4/base_fw.h>
#include <rimage/sof/user/manifest.h>

Expand All @@ -30,6 +34,20 @@ struct ipc4_modules_info {
struct sof_man_module modules[0];
} __packed __aligned(4);

struct ipc4_uaol_link_capabilities {
uint32_t input_streams_supported : 4;
uint32_t output_streams_supported : 4;
uint32_t bidirectional_streams_supported : 5;
uint32_t rsvd : 19;
uint32_t max_tx_fifo_size;
uint32_t max_rx_fifo_size;
} __packed __aligned(4);

struct ipc4_uaol_capabilities {
uint32_t link_count;
struct ipc4_uaol_link_capabilities link_caps[];
} __packed __aligned(4);
tlissows marked this conversation as resolved.
Show resolved Hide resolved

/*
* TODO: default to value of ACE1.x platforms. This is defined
* in multiple places in Zephyr, mm_drv_intel_adsp.h and
Expand All @@ -54,7 +72,7 @@ int basefw_vendor_fw_config(uint32_t *data_offset, char *data)
tlv_value_uint32_set(tuple, IPC4_SLOW_CLOCK_FREQ_HZ_FW_CFG, IPC4_ALH_CAVS_1_8);

tuple = tlv_next(tuple);
tlv_value_uint32_set(tuple, IPC4_UAOL_SUPPORT, 0);
tlv_value_uint32_set(tuple, IPC4_UAOL_SUPPORT, 1);

tuple = tlv_next(tuple);
tlv_value_uint32_set(tuple, IPC4_ALH_SUPPORT_LEVEL_FW_CFG, IPC4_ALH_CAVS_1_8);
Expand All @@ -65,6 +83,41 @@ int basefw_vendor_fw_config(uint32_t *data_offset, char *data)
return 0;
}

#if CONFIG_UAOL_INTEL_ADSP

#define UAOL_DEV(node) DEVICE_DT_GET(node),
static const struct device *uaol_devs[] = {
DT_FOREACH_STATUS_OKAY(intel_adsp_uaol, UAOL_DEV)
};

static void tlv_value_set_uaol_caps(struct sof_tlv *tuple, uint32_t type)
{
unsigned int dev_count = ARRAY_SIZE(uaol_devs);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const ?

struct uaol_capabilities dev_cap;
struct ipc4_uaol_capabilities *caps = (struct ipc4_uaol_capabilities *)tuple->value;
size_t caps_size = offsetof(struct ipc4_uaol_capabilities, link_caps[dev_count]);
unsigned int i;
int ret;

memset(caps, 0, caps_size);

caps->link_count = dev_count;
for (i = 0; i < dev_count; i++) {
ret = uaol_get_capabilities(uaol_devs[i], &dev_cap);
if (ret)
continue;

caps->link_caps[i].input_streams_supported = dev_cap.input_streams;
caps->link_caps[i].output_streams_supported = dev_cap.output_streams;
caps->link_caps[i].bidirectional_streams_supported = dev_cap.bidirectional_streams;
caps->link_caps[i].max_tx_fifo_size = dev_cap.max_tx_fifo_size;
caps->link_caps[i].max_rx_fifo_size = dev_cap.max_rx_fifo_size;
}

tlv_value_set(tuple, type, caps_size, caps);
}
#endif

int basefw_vendor_hw_config(uint32_t *data_offset, char *data)
{
struct sof_tlv *tuple = (struct sof_tlv *)data;
Expand Down Expand Up @@ -93,6 +146,11 @@ int basefw_vendor_hw_config(uint32_t *data_offset, char *data)
tlv_value_uint32_set(tuple, IPC4_I2S_CAPS_HW_CFG, I2S_VER_30_PTL);
#endif

#if CONFIG_UAOL_INTEL_ADSP
tuple = tlv_next(tuple);
tlv_value_set_uaol_caps(tuple, IPC4_UAOL_CAPS_HW_CFG);
#endif

tuple = tlv_next(tuple);
*data_offset = (int)((char *)tuple - data);

Expand Down Expand Up @@ -358,6 +416,10 @@ int basefw_vendor_dma_control(uint32_t node_id, const char *config_data, size_t
case ipc4_i2s_link_input_class:
type = DAI_INTEL_SSP;
break;
case ipc4_alh_uaol_stream_link_output_class:
case ipc4_alh_uaol_stream_link_input_class:
type = DAI_INTEL_UAOL;
break;
default:
return IPC4_INVALID_RESOURCE_ID;
}
Expand Down
2 changes: 2 additions & 0 deletions src/audio/copier/copier.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ static int copier_init(struct processing_module *mod)
case ipc4_i2s_link_input_class:
case ipc4_alh_link_output_class:
case ipc4_alh_link_input_class:
case ipc4_alh_uaol_stream_link_output_class:
case ipc4_alh_uaol_stream_link_input_class:
ret = copier_dai_create(dev, cd, copier, ipc_pipe->pipeline);
if (ret < 0) {
comp_err(dev, "unable to create dai");
Expand Down
13 changes: 13 additions & 0 deletions src/audio/copier/copier_dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,19 @@ int copier_dai_create(struct comp_dev *dev, struct copier_data *cd,
if (ret)
return ret;
break;
case ipc4_alh_uaol_stream_link_output_class:
case ipc4_alh_uaol_stream_link_input_class:
dai.type = SOF_DAI_INTEL_UAOL;
dai.is_config_blob = true;
cd->gtw_type = ipc4_gtw_alh;
ret = ipc4_find_dma_config(&dai, (uint8_t *)cd->gtw_cfg,
copier->gtw_cfg.config_length * 4);
if (ret != IPC4_SUCCESS) {
comp_err(dev, "No uaol dma_config found in blob!");
return -EINVAL;
}
dai.out_fmt = &copier->out_fmt;
break;
case ipc4_dmic_link_input_class:
dai.type = SOF_DAI_INTEL_DMIC;
dai.is_config_blob = true;
Expand Down
16 changes: 12 additions & 4 deletions src/audio/dai-zephyr.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ int dai_set_config(struct dai *dai, struct ipc_config_dai *common_config,
{
const struct device *dev = dai->dev;
const struct sof_ipc_dai_config *sof_cfg = spec_config;
const struct ipc4_copier_gateway_cfg *gtw_cfg = spec_config;
struct dai_config cfg;
const void *cfg_params;
bool is_blob;
Expand All @@ -149,29 +150,31 @@ int dai_set_config(struct dai *dai, struct ipc_config_dai *common_config,
cfg.format = sof_cfg->format;
cfg.options = sof_cfg->flags;
cfg.rate = common_config->sampling_frequency;
cfg.channels = common_config->out_fmt->channels_count;
cfg.word_size = common_config->out_fmt->valid_bit_depth;

switch (common_config->type) {
case SOF_DAI_INTEL_SSP:
cfg.type = is_blob ? DAI_INTEL_SSP_NHLT : DAI_INTEL_SSP;
cfg_params = is_blob ? spec_config : &sof_cfg->ssp;
cfg_params = is_blob ? (void *)&gtw_cfg->config_data : &sof_cfg->ssp;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the void* cast here or is the compiler throwing up a warning in this case ? cfg_params is also const too.

dai_set_link_hda_config(&cfg.link_config,
common_config, cfg_params);
/* Store tdm slot group index*/
cfg.tdm_slot_group = common_config->dai_index & 0xF;
break;
case SOF_DAI_INTEL_ALH:
cfg.type = is_blob ? DAI_INTEL_ALH_NHLT : DAI_INTEL_ALH;
cfg_params = is_blob ? spec_config : &sof_cfg->alh;
cfg_params = is_blob ? (void *)&gtw_cfg->config_data : &sof_cfg->alh;
break;
case SOF_DAI_INTEL_DMIC:
cfg.type = is_blob ? DAI_INTEL_DMIC_NHLT : DAI_INTEL_DMIC;
cfg_params = is_blob ? spec_config : &sof_cfg->dmic;
cfg_params = is_blob ? (void *)&gtw_cfg->config_data : &sof_cfg->dmic;
dai_set_link_hda_config(&cfg.link_config,
common_config, cfg_params);
break;
case SOF_DAI_INTEL_HDA:
cfg.type = is_blob ? DAI_INTEL_HDA_NHLT : DAI_INTEL_HDA;
cfg_params = is_blob ? spec_config : &sof_cfg->hda;
cfg_params = is_blob ? (void *)&gtw_cfg->config_data : &sof_cfg->hda;
break;
case SOF_DAI_IMX_SAI:
cfg.type = DAI_IMX_SAI;
Expand All @@ -181,6 +184,11 @@ int dai_set_config(struct dai *dai, struct ipc_config_dai *common_config,
cfg.type = DAI_IMX_ESAI;
cfg_params = &sof_cfg->esai;
break;
case SOF_DAI_INTEL_UAOL:
cfg.type = DAI_INTEL_UAOL;
cfg_params = gtw_cfg;
dai_set_link_hda_config(&cfg.link_config, common_config, &gtw_cfg->config_data);
break;
default:
return -EINVAL;
}
Expand Down
3 changes: 2 additions & 1 deletion src/include/ipc/dai.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ enum sof_ipc_dai_type {
SOF_DAI_AMD_SP_VIRTUAL, /**<Amd SP VIRTUAL */
SOF_DAI_AMD_HS_VIRTUAL, /**<Amd HS VIRTUAL */
SOF_DAI_IMX_MICFIL, /**< i.MX MICFIL */
SOF_DAI_AMD_SW_AUDIO /**<Amd SW AUDIO */
SOF_DAI_AMD_SW_AUDIO, /**<Amd SW AUDIO */
SOF_DAI_INTEL_UAOL, /**< Intel UAOL */
};

/* general purpose DAI configuration */
Expand Down
25 changes: 24 additions & 1 deletion src/ipc/ipc4/dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ void dai_set_link_hda_config(uint16_t *link_config,
}
link_cfg.part.stream = common_config->host_dma_config[0]->stream_id;
break;
case SOF_DAI_INTEL_UAOL:
link_cfg.full = 0;
link_cfg.part.hchan = out_fmt->channels_count - 1;
link_cfg.part.dir = common_config->direction;
link_cfg.part.stream = common_config->host_dma_config[0]->stream_id;
break;
default:
/* other types of DAIs not need link_config */
return;
Expand Down Expand Up @@ -115,6 +121,13 @@ int dai_config_dma_channel(struct dai_data *dd, struct comp_dev *dev, const void
*/
channel = 0;
break;
#if ACE_VERSION > ACE_VERSION_1_5
case SOF_DAI_INTEL_UAOL:
channel = 0;
if (dai->host_dma_config[0]->pre_allocated_by_host)
channel = dai->host_dma_config[0]->dma_channel_id;
break;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't fully understand this.

for LNL+ all the DMA stuff is handled in the same way with an HDaudio-based solution.

We just moved some of the ALH stuff into the HDaudio prodessing - see line 94 the test for ALH.

so shouldn't the UAOL stuff also be moved under the HDAudio category? Why special case what looks identical?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my comment still stands.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tlissows any update here ?

#endif
default:
/* other types of DAIs not handled for now */
comp_err(dev, "dai_config_dma_channel(): Unknown dai type %d", dai->type);
Expand Down Expand Up @@ -177,6 +190,16 @@ int ipc_dai_data_config(struct dai_data *dd, struct comp_dev *dev)
dev->ipc_config.frame_fmt, dd->stream_id);

break;
case SOF_DAI_INTEL_UAOL:
#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS
dd->stream_id = dai_get_stream_id(dai_p, dai->direction);
dev->ipc_config.frame_fmt = SOF_IPC_FRAME_S32_LE;
dd->config.burst_elems = dai_get_fifo_depth(dd->dai, dai->direction);
break;
#else
/* only native Zephyr driver supported */
return -EINVAL;
#endif
default:
/* other types of DAIs not handled for now */
comp_warn(dev, "dai_data_config(): Unknown dai type %d", dai->type);
Expand Down Expand Up @@ -393,7 +416,7 @@ int dai_config(struct dai_data *dd, struct comp_dev *dev, struct ipc_config_dai
if (ret < 0)
return ret;

return dai_set_config(dd->dai, common_config, copier_cfg->gtw_cfg.config_data);
return dai_set_config(dd->dai, common_config, &copier_cfg->gtw_cfg);
}

#if CONFIG_ZEPHYR_NATIVE_DRIVERS
Expand Down
12 changes: 12 additions & 0 deletions src/ipc/ipc4/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -1101,6 +1101,18 @@ int ipc4_add_comp_dev(struct comp_dev *dev)
int ipc4_find_dma_config(struct ipc_config_dai *dai, uint8_t *data_buffer, uint32_t size)
{
#if ACE_VERSION > ACE_VERSION_1_5
if (dai->type == SOF_DAI_INTEL_UAOL) {
void *value_ptr = NULL;
uint32_t value_size;

tlv_value_get(data_buffer, size, GTW_DMA_CONFIG_ID, &value_ptr, &value_size);
if (!value_ptr)
return IPC4_INVALID_REQUEST;

dai->host_dma_config[0] = (struct ipc_dma_config *)value_ptr;
return IPC4_SUCCESS;
}

uint32_t *dma_config_id = GET_IPC_DMA_CONFIG_ID(data_buffer, size);

if (*dma_config_id != GTW_DMA_CONFIG_ID)
Expand Down
47 changes: 45 additions & 2 deletions src/lib/dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ const struct device *zephyr_dev[] = {
#if CONFIG_DAI_NXP_ESAI
DT_FOREACH_STATUS_OKAY(nxp_dai_esai, GET_DEVICE_LIST)
#endif
#if CONFIG_DAI_INTEL_UAOL
DT_FOREACH_STATUS_OKAY(intel_uaol_dai, GET_DEVICE_LIST)
#endif
};

const struct device *dai_get_device(uint32_t type, uint32_t index)
Expand All @@ -157,7 +160,7 @@ const struct device *dai_get_device(uint32_t type, uint32_t index)
int dir;
int i;

dir = (type == SOF_DAI_INTEL_DMIC) ? DAI_DIR_RX : DAI_DIR_BOTH;
dir = (type == DAI_INTEL_DMIC) ? DAI_DIR_RX : DAI_DIR_BOTH;

for (i = 0; i < ARRAY_SIZE(zephyr_dev); i++) {
if (dai_config_get(zephyr_dev[i], &cfg, dir))
Expand Down Expand Up @@ -197,6 +200,7 @@ static void dai_set_device_params(struct dai *d)
#endif
break;
case SOF_DAI_INTEL_HDA:
case SOF_DAI_INTEL_UAOL:
d->dma_dev = DMA_DEV_HDA;
d->dma_caps = DMA_CAP_HDA;
break;
Expand All @@ -210,8 +214,47 @@ struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags)
{
const struct device *dev;
struct dai *d;
uint32_t z_type;

switch (type) {
case SOF_DAI_INTEL_SSP:
z_type = DAI_INTEL_SSP;
break;
case SOF_DAI_INTEL_DMIC:
z_type = DAI_INTEL_DMIC;
break;
case SOF_DAI_INTEL_HDA:
z_type = DAI_INTEL_HDA;
break;
case SOF_DAI_INTEL_ALH:
z_type = DAI_INTEL_ALH;
break;
case SOF_DAI_IMX_SAI:
z_type = DAI_IMX_SAI;
break;
case SOF_DAI_IMX_ESAI:
z_type = DAI_IMX_ESAI;
break;
case SOF_DAI_AMD_BT:
z_type = DAI_AMD_BT;
break;
case SOF_DAI_AMD_SP:
z_type = DAI_AMD_SP;
break;
case SOF_DAI_AMD_DMIC:
z_type = DAI_AMD_DMIC;
break;
case SOF_DAI_MEDIATEK_AFE:
z_type = DAI_MEDIATEK_AFE;
break;
case SOF_DAI_INTEL_UAOL:
z_type = DAI_INTEL_UAOL;
break;
default:
return NULL;
}
tlissows marked this conversation as resolved.
Show resolved Hide resolved

dev = dai_get_device(type, index);
dev = dai_get_device(z_type, index);
if (!dev) {
tr_err(&dai_tr, "dai_get: failed to get dai with index %d type %d",
index, type);
Expand Down
Loading