Skip to content

Commit

Permalink
copier: dai: use HD-A dai to configure soundwire on LNL
Browse files Browse the repository at this point in the history
Since LNL soundwire uses HD-A DMA to transfer data. Add LNL specific
configuration to select HD-A DMA in case of SoundWire audio interface.
Refactor copier dai code for sndw/alh node id type.

Add support for sndw link aggregation mode for LNL platform based on
DMA config being sent during Copier Init Instance IPC.

Signed-off-by: Ievgen Ganakov <ievgen.ganakov@intel.com>
  • Loading branch information
iganakov authored and kv2019i committed Jan 29, 2024
1 parent 21bcf73 commit a1deb74
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 43 deletions.
145 changes: 102 additions & 43 deletions src/audio/copier/copier_dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,96 @@ static int copier_set_alh_multi_gtw_channel_map(struct comp_dev *dev,
return 0;
}

static int copier_alh_assign_dai_index(struct comp_dev *dev,
void *gtw_cfg_data,
union ipc4_connector_node_id node_id,
struct ipc_config_dai *dai,
int *dai_index,
int *dai_count)
{
struct processing_module *mod = comp_get_drvdata(dev);
struct copier_data *cd = module_get_private_data(mod);
const struct sof_alh_configuration_blob *alh_blob = gtw_cfg_data;
uint8_t *dma_config;
size_t alh_cfg_size, dma_config_length;
int i, dai_num, ret;

if (!cd->config.gtw_cfg.config_length) {
comp_err(mod->dev, "No gateway config found in blob!");
return -EINVAL;
}

switch (dai->type) {
case SOF_DAI_INTEL_HDA:
/* We use DAI_INTEL_HDA for ACE 2.0 platforms */
alh_cfg_size = get_alh_config_size(alh_blob);
dma_config = (uint8_t *)gtw_cfg_data + alh_cfg_size;
dma_config_length = (cd->config.gtw_cfg.config_length << 2) - alh_cfg_size;

/* Here we check node_id if we need to use FW aggregation,
* in other words do we need to create multiple dai or not
*/
if (!is_multi_gateway(node_id)) {
/* Find DMA config in blob and retrieve stream_id */
ret = ipc4_find_dma_config_multiple(dai, dma_config, dma_config_length,
alh_blob->alh_cfg.mapping[0].alh_id, 0);
if (ret != 0) {
comp_err(mod->dev, "No sndw dma_config found in blob!");
return -EINVAL;
}
dai_index[0] = dai->host_dma_config[0]->stream_id;
return 0;
}

dai_num = alh_blob->alh_cfg.count;
if (dai_num > IPC4_ALH_MAX_NUMBER_OF_GTW || dai_num < 0) {
comp_err(mod->dev, "Invalid dai_count: %d", dai_num);
return -EINVAL;
}

for (i = 0; i < dai_num; i++) {
ret = ipc4_find_dma_config_multiple(dai, dma_config,
dma_config_length,
alh_blob->alh_cfg.mapping[i].alh_id, i);
if (ret != 0) {
comp_err(mod->dev, "No sndw dma_config found in blob!");
return -EINVAL;
}

/* To process data on SoundWire interface HD-A DMA is used so it seems
* logical to me to use stream tag as a dai_index instead of PDI.
*/
dai_index[i] = dai->host_dma_config[i]->stream_id;
}

*dai_count = dai_num;
break;
case SOF_DAI_INTEL_ALH:
/* Use DAI_INTEL_ALH for ACE 1.0 and older */
if (!is_multi_gateway(node_id)) {
dai_index[0] = IPC4_ALH_DAI_INDEX(node_id.f.v_index);
return 0;
}

dai_num = alh_blob->alh_cfg.count;
if (dai_num > IPC4_ALH_MAX_NUMBER_OF_GTW || dai_num < 0) {
comp_err(mod->dev, "Invalid dai_count: %d", dai_num);
return -EINVAL;
}

for (i = 0; i < dai_num; i++)
dai_index[i] = IPC4_ALH_DAI_INDEX(alh_blob->alh_cfg.mapping[i].alh_id);

*dai_count = dai_num;
break;
default:
comp_err(mod->dev, "Invalid dai type selected: %d", dai->type);
return -EINVAL;
}

return 0;
}

static int copier_dai_init(struct comp_dev *dev,
struct comp_ipc_config *config,
const struct ipc4_copier_module_cfg *copier,
Expand Down Expand Up @@ -100,7 +190,8 @@ static int copier_dai_init(struct comp_dev *dev,
}

/* save the channel map and count for ALH multi-gateway */
if (type == ipc4_gtw_alh && is_multi_gateway(copier->gtw_cfg.node_id)) {
if ((type == ipc4_gtw_alh || type == ipc4_gtw_link) &&
is_multi_gateway(copier->gtw_cfg.node_id)) {
ret = copier_set_alh_multi_gtw_channel_map(dev, copier, index);
if (ret < 0)
return ret;
Expand Down Expand Up @@ -182,50 +273,19 @@ int copier_dai_create(struct comp_dev *dev, struct copier_data *cd,
break;
case ipc4_alh_link_output_class:
case ipc4_alh_link_input_class:
#if defined(CONFIG_ACE_VERSION_2_0)
dai.type = SOF_DAI_INTEL_HDA;
dai.is_config_blob = true;
type = ipc4_gtw_link;
#else
dai.type = SOF_DAI_INTEL_ALH;
dai.is_config_blob = true;
type = ipc4_gtw_alh;

/* copier
* {
* gtw_cfg
* {
* gtw_node_id;
* config_length;
* config_data
* {
* count;
* {
* node_id; \\ normal gtw id
* mask;
* } mapping[MAX_ALH_COUNT];
* }
* }
* }
*/
/* get gtw node id in config data */
if (is_multi_gateway(node_id)) {
if (copier->gtw_cfg.config_length) {
const struct sof_alh_configuration_blob *alh_blob =
(const struct sof_alh_configuration_blob *)
copier->gtw_cfg.config_data;

dai_count = alh_blob->alh_cfg.count;
if (dai_count > IPC4_ALH_MAX_NUMBER_OF_GTW || dai_count < 0) {
comp_err(dev, "Invalid dai_count: %d", dai_count);
return -EINVAL;
}
for (i = 0; i < dai_count; i++)
dai_index[i] =
IPC4_ALH_DAI_INDEX(alh_blob->alh_cfg.mapping[i].alh_id);
} else {
comp_err(dev, "No ipc4_alh_multi_gtw_cfg found in blob!");
return -EINVAL;
}
} else {
dai_index[dai_count - 1] = IPC4_ALH_DAI_INDEX(node_id.f.v_index);
}

#endif /* defined(CONFIG_ACE_VERSION_2_0) */
ret = copier_alh_assign_dai_index(dev, cd->gtw_cfg, node_id,
&dai, dai_index, &dai_count);
if (ret)
return ret;
break;
case ipc4_dmic_link_input_class:
dai.type = SOF_DAI_INTEL_DMIC;
Expand Down Expand Up @@ -425,7 +485,6 @@ int copier_dai_params(struct copier_data *cd, struct comp_dev *dev,
cd->converter[IPC4_COPIER_GATEWAY_PIN];
return ret;
}

/* For ALH multi-gateway case, params->channels is a total multiplexed
* number of channels. Demultiplexed number of channels for each individual
* gateway comes in blob's struct ipc4_alh_multi_gtw_cfg.
Expand Down
8 changes: 8 additions & 0 deletions src/include/ipc4/alh.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,12 @@ struct sof_alh_configuration_blob {
struct ipc4_alh_multi_gtw_cfg alh_cfg;
} __attribute__((packed, aligned(4)));

static inline size_t
get_alh_config_size(const struct sof_alh_configuration_blob *alh_blob)
{
return sizeof(alh_blob->gtw_attributes) +
sizeof(alh_blob->alh_cfg.count) +
sizeof(alh_blob->alh_cfg.mapping[0]) * alh_blob->alh_cfg.count;
}

#endif
24 changes: 24 additions & 0 deletions src/ipc/ipc4/dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <sof/audio/module_adapter/module/generic.h>

#include "../audio/copier/copier.h"
#include "../audio/copier/dai_copier.h"
Expand Down Expand Up @@ -84,6 +85,29 @@ int dai_config_dma_channel(struct dai_data *dd, struct comp_dev *dev, const void
#endif
break;
case SOF_DAI_INTEL_HDA:
#if defined(CONFIG_ACE_VERSION_2_0)
if (copier_cfg->gtw_cfg.node_id.f.dma_type == ipc4_alh_link_output_class ||
copier_cfg->gtw_cfg.node_id.f.dma_type == ipc4_alh_link_input_class) {
struct processing_module *mod = comp_get_drvdata(dev);
struct copier_data *cd = module_get_private_data(mod);

if (!cd->gtw_cfg) {
comp_err(dev, "No gateway config found!");
return DMA_CHAN_INVALID;
}

channel = DMA_CHAN_INVALID;
const struct sof_alh_configuration_blob *alh_blob = cd->gtw_cfg;

for (int i = 0; i < alh_blob->alh_cfg.count; i++) {
if (dai->host_dma_config[i]->stream_id == dai->dai_index) {
channel = dai->host_dma_config[i]->dma_channel_id;
break;
}
}
break;
}
#endif /* defined(CONFIG_ACE_VERSION_2_0) */
channel = copier_cfg->gtw_cfg.node_id.f.v_index;
break;
case SOF_DAI_INTEL_ALH:
Expand Down

0 comments on commit a1deb74

Please sign in to comment.