Skip to content

Commit

Permalink
LNL: Add hda_dma_config for interfaces
Browse files Browse the repository at this point in the history
In LNL the GPDMA engine was removed. Instead HD Audio
Link DMA is used to transport data over audio interfaces.
Since HD Audio is a Host managed engine, the link configuration
is passed through IPCv4.
The configuration must be forwarded to appropriate interface driver
to configure HW.

Signed-off-by: Jaroslaw Stelter <[email protected]>
  • Loading branch information
jxstelter authored and kv2019i committed May 24, 2023
1 parent 2df3cba commit 22ad526
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 5 deletions.
22 changes: 17 additions & 5 deletions src/audio/copier/copier.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ static int create_dai(struct comp_dev *parent_dev, struct copier_data *cd,
const struct comp_driver *drv;
struct ipc_config_dai dai;
int dai_count;
int i;
int i, ret;

drv = ipc4_get_drv((uint8_t *)&id);
if (!drv)
Expand Down Expand Up @@ -415,6 +415,13 @@ static int create_dai(struct comp_dev *parent_dev, struct copier_data *cd,
dai.type = SOF_DAI_INTEL_SSP;
dai.is_config_blob = true;
type = ipc4_gtw_ssp;
ret = ipc4_find_dma_config(&dai, (uint8_t *)copier->gtw_cfg.config_data,
copier->gtw_cfg.config_length * 4);
if (ret != 0) {
comp_err(parent_dev, "No ssp dma_config found in blob!");
return -EINVAL;
}
dai.out_fmt = &copier->out_fmt;
break;
case ipc4_alh_link_output_class:
case ipc4_alh_link_input_class:
Expand Down Expand Up @@ -467,14 +474,20 @@ static int create_dai(struct comp_dev *parent_dev, struct copier_data *cd,
dai.type = SOF_DAI_INTEL_DMIC;
dai.is_config_blob = true;
type = ipc4_gtw_dmic;

ret = ipc4_find_dma_config(&dai, (uint8_t *)copier->gtw_cfg.config_data,
copier->gtw_cfg.config_length * 4);
if (ret != 0) {
comp_err(parent_dev, "No dmic dma_config found in blob!");
return -EINVAL;
}
dai.out_fmt = &copier->out_fmt;
break;
default:
return -EINVAL;
}

for (i = 0; i < dai_count; i++) {
int ret;

dai.dai_index = dai_index[i];
ret = init_dai(parent_dev, drv, config, copier, pipeline, &dai, type, i,
dai_count);
Expand All @@ -495,8 +508,7 @@ static int create_dai(struct comp_dev *parent_dev, struct copier_data *cd,

/* create multi_endpoint_buffer for ALH multi-gateway case */
if (dai_count > 1) {
int ret = create_endpoint_buffer(parent_dev, cd, config, copier, type, true, 0);

ret = create_endpoint_buffer(parent_dev, cd, config, copier, type, true, 0);
if (ret < 0)
return ret;
}
Expand Down
4 changes: 4 additions & 0 deletions src/audio/dai-zephyr.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ int dai_set_config(struct dai *dai, struct ipc_config_dai *common_config,
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;
dai_set_link_hda_config(&cfg.link_config,
common_config, cfg_params);
break;
case SOF_DAI_INTEL_ALH:
cfg.type = is_blob ? DAI_INTEL_ALH_NHLT : DAI_INTEL_ALH;
Expand All @@ -151,6 +153,8 @@ int dai_set_config(struct dai *dai, struct ipc_config_dai *common_config,
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;
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;
Expand Down
4 changes: 4 additions & 0 deletions src/include/ipc4/alh.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@
#include <ipc4/gateway.h>

#define IPC4_ALH_MAX_NUMBER_OF_GTW 16
#ifdef CONFIG_DMA_INTEL_ADSP_GPDMA
#define IPC4_ALH_DAI_INDEX_OFFSET 7
#else
#define IPC4_ALH_DAI_INDEX_OFFSET 0
#endif

/* copier id = (group id << 4) + codec id + IPC4_ALH_DAI_INDEX_OFFSET
* dai_index = (group id << 8) + codec id;
Expand Down
40 changes: 40 additions & 0 deletions src/include/sof/audio/ipc-config.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,42 @@
#include <stdint.h>
#include <stdbool.h>

/* ACE 2.0 and newer */
#define GTW_DMA_CONFIG_ID 0x1000
#define GTW_DMA_INVALID_CHANNEL_ID 0xffffffff
/* Maximum number of devices */
#define GTW_DMA_DEVICE_MAX_COUNT 16

struct dma_device_stream_channel_map {
uint32_t device_address;
uint32_t channel_map;
};

struct dma_stream_channel_map {
uint32_t device_count;
struct dma_device_stream_channel_map map[GTW_DMA_DEVICE_MAX_COUNT];
};

struct ipc_dma_config {
uint8_t dma_method; /**< DMA method */
uint8_t pre_allocated_by_host; /**< 1 - DMA pre-allocated by host, otherwise to be
* allocated by DSP
*/
uint16_t rsvd;
uint32_t dma_channel_id; /**< channel ID if DMA pre-allocated by host, otherwise
* invalid channel ID
*/
uint32_t stream_id;
/* DmaStreamChannelMap */
struct dma_stream_channel_map channel_map;
uint32_t dma_priv_config_size;
uint8_t dma_priv_config[0];
} __attribute__((packed, aligned(4)));

#define GET_IPC_DMA_CONFIG(buffer, size) \
((struct ipc_dma_config *)((uint8_t *)(buffer) + (size) - sizeof(struct ipc_dma_config)))
#define GET_IPC_DMA_CONFIG_ID(buffer, size) ((uint32_t *)GET_IPC_DMA_CONFIG(buffer, size) - 2)

/*
* Generic IPC information for base components. Fields can be added here with NO impact on
* IPC ABI version.
Expand Down Expand Up @@ -39,6 +75,10 @@ struct ipc_config_dai {
uint32_t feature_mask; /**< copier feature mask (set directly from
* ipc4_copier_module_cfg on init)
*/
struct ipc_dma_config *host_dma_config; /**< DMA config - required for ACE 2.0 and newer */
const struct ipc4_audio_format *out_fmt;/**< audio format for output pin 0 - required
* for ACE 2.0 and newer
*/
};

/* generic volume component */
Expand Down
1 change: 1 addition & 0 deletions src/include/sof/ipc/topology.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ int ipc4_create_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma);
int ipc4_trigger_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma, bool *delay);
int ipc4_process_on_core(uint32_t core, bool blocking);
int ipc4_pipeline_complete(struct ipc *ipc, uint32_t comp_id);
int ipc4_find_dma_config(struct ipc_config_dai *dai, uint8_t *data_buffer, uint32_t size);
#else
#error "No or invalid IPC MAJOR version selected."
#endif
Expand Down
7 changes: 7 additions & 0 deletions src/include/sof/lib/dai-legacy.h
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,13 @@ static inline const struct dai_info *dai_info_get(void)
*/
int dai_config_dma_channel(struct dai_data *dd, struct comp_dev *dev, const void *config);

/**
* \brief Configure HD Audio DMA params for DAI
*/
void dai_set_link_hda_config(uint16_t *link_config,
struct ipc_config_dai *common_config,
const void *spec_config);

/**
* \brief Reset DAI DMA config
*/
Expand Down
16 changes: 16 additions & 0 deletions src/include/sof/lib/dai-zephyr.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ struct timestamp_ops {
struct timestamp_data *tsd);
};

union hdalink_cfg {
uint16_t full;
struct {
uint16_t lchan :4;
uint16_t hchan :4;
uint16_t stream :6;
uint16_t rsvd :1;
uint16_t dir :1;
} part;
};
/**
* \brief DAI group information
*/
Expand Down Expand Up @@ -255,6 +265,12 @@ int dai_get_stream_id(struct dai *dai, int direction);
*/
int dai_config_dma_channel(struct dai_data *dd, struct comp_dev *dev, const void *config);

/**
* \brief Configure HD Audio DMA params for DAI
*/
void dai_set_link_hda_config(uint16_t *link_config,
struct ipc_config_dai *common_config,
const void *spec_config);
/**
* \brief Reset DAI DMA config
*/
Expand Down
5 changes: 5 additions & 0 deletions src/ipc/ipc3/dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@

LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL);

void dai_set_link_hda_config(uint16_t *link_config,
struct ipc_config_dai *common_config,
const void *spec_config)
{ }

int dai_config_dma_channel(struct dai_data *dd, struct comp_dev *dev, const void *spec_config)
{
const struct sof_ipc_dai_config *config = spec_config;
Expand Down
40 changes: 40 additions & 0 deletions src/ipc/ipc4/dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,42 @@

LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL);

void dai_set_link_hda_config(uint16_t *link_config,
struct ipc_config_dai *common_config,
const void *spec_config)
{
#if defined(CONFIG_ACE_VERSION_2_0)
const struct ipc4_audio_format *out_fmt = common_config->out_fmt;
const struct sof_ipc_dai_config *sof_cfg = spec_config;
union hdalink_cfg link_cfg;

switch (common_config->type) {
case SOF_DAI_INTEL_SSP:
link_cfg.full = 0;
link_cfg.part.dir = common_config->direction;
link_cfg.part.stream = common_config->host_dma_config->stream_id;
break;
case SOF_DAI_INTEL_DMIC:
link_cfg.full = 0;
if (out_fmt->depth == IPC4_DEPTH_16BIT) {
/* 16bit dmic packs two 16bit samples into single 32bit word
* fw needs to adjust channel count to match final sample
* group size
*/
link_cfg.part.hchan = (out_fmt->channels_count - 1) / 2;
} else {
link_cfg.part.hchan = out_fmt->channels_count - 1;
}
link_cfg.part.stream = common_config->host_dma_config->stream_id;
break;
default:
/* other types of DAIs not need link_config */
return;
}
*link_config = link_cfg.full;
#endif
}

int dai_config_dma_channel(struct dai_data *dd, struct comp_dev *dev, const void *spec_config)
{
const struct ipc4_copier_module_cfg *copier_cfg = spec_config;
Expand All @@ -42,6 +78,10 @@ int dai_config_dma_channel(struct dai_data *dd, struct comp_dev *dev, const void
COMPILER_FALLTHROUGH;
case SOF_DAI_INTEL_DMIC:
channel = 0;
#if defined(CONFIG_ACE_VERSION_2_0)
if (dai->host_dma_config->pre_allocated_by_host)
channel = dai->host_dma_config->dma_channel_id;
#endif
break;
case SOF_DAI_INTEL_HDA:
channel = copier_cfg->gtw_cfg.node_id.f.v_index;
Expand Down
14 changes: 14 additions & 0 deletions src/ipc/ipc4/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -789,3 +789,17 @@ int ipc4_add_comp_dev(struct comp_dev *dev)

return IPC4_SUCCESS;
};

int ipc4_find_dma_config(struct ipc_config_dai *dai, uint8_t *data_buffer, uint32_t size)
{
#if defined(CONFIG_ACE_VERSION_2_0)
uint32_t *dma_config_id = GET_IPC_DMA_CONFIG_ID(data_buffer, size);

if (*dma_config_id != GTW_DMA_CONFIG_ID)
return IPC4_INVALID_REQUEST;

dai->host_dma_config = GET_IPC_DMA_CONFIG(data_buffer, size);
#endif
return IPC4_SUCCESS;
}

12 changes: 12 additions & 0 deletions src/lib/dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,15 +170,27 @@ static void dai_set_device_params(struct dai *d)
switch (d->type) {
case SOF_DAI_INTEL_SSP:
d->dma_dev = DMA_DEV_SSP;
#ifdef CONFIG_DMA_INTEL_ADSP_GPDMA
d->dma_caps = DMA_CAP_GP_LP | DMA_CAP_GP_HP;
#else
d->dma_caps = DMA_CAP_HDA;
#endif
break;
case SOF_DAI_INTEL_DMIC:
d->dma_dev = DMA_DEV_DMIC;
#ifdef CONFIG_DMA_INTEL_ADSP_GPDMA
d->dma_caps = DMA_CAP_GP_LP | DMA_CAP_GP_HP;
#else
d->dma_caps = DMA_CAP_HDA;
#endif
break;
case SOF_DAI_INTEL_ALH:
d->dma_dev = DMA_DEV_ALH;
#ifdef CONFIG_DMA_INTEL_ADSP_GPDMA
d->dma_caps = DMA_CAP_GP_LP | DMA_CAP_GP_HP;
#else
d->dma_caps = DMA_CAP_HDA;
#endif
break;
case SOF_DAI_INTEL_HDA:
d->dma_dev = DMA_DEV_HDA;
Expand Down

0 comments on commit 22ad526

Please sign in to comment.