Skip to content
Merged
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
63 changes: 5 additions & 58 deletions sound/soc/sof/intel/hda-dai-ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,17 +145,9 @@ static struct hdac_ext_stream *hda_assign_hext_stream(struct snd_sof_dev *sdev,
struct snd_soc_dai *cpu_dai,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *dai;
struct hdac_ext_stream *hext_stream;

/* only allocate a stream_tag for the first DAI in the dailink */
dai = snd_soc_rtd_to_cpu(rtd, 0);
if (dai == cpu_dai)
hext_stream = hda_link_stream_assign(sof_to_bus(sdev), substream);
else
hext_stream = snd_soc_dai_get_dma_data(dai, substream);

hext_stream = hda_link_stream_assign(sof_to_bus(sdev), substream);
if (!hext_stream)
return NULL;

Expand All @@ -168,14 +160,9 @@ static void hda_release_hext_stream(struct snd_sof_dev *sdev, struct snd_soc_dai
struct snd_pcm_substream *substream)
{
struct hdac_ext_stream *hext_stream = hda_get_hext_stream(sdev, cpu_dai, substream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *dai;

/* only release a stream_tag for the first DAI in the dailink */
dai = snd_soc_rtd_to_cpu(rtd, 0);
if (dai == cpu_dai)
snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK);
snd_soc_dai_set_dma_data(cpu_dai, substream, NULL);
snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK);
}

static void hda_setup_hext_stream(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream,
Expand Down Expand Up @@ -239,34 +226,16 @@ static unsigned int generic_calc_stream_format(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai_link_ch_map *ch_maps;
unsigned int format_val;
unsigned int bits;
int num_channels;
u32 ch_mask = 0;
int i;

/*
* if the multiple dais are handled by the same dailink, we may need to update the
* stream channel count - the params are modified in soc-pcm based on the ch_maps info
*/
for_each_link_ch_maps(rtd->dai_link, i, ch_maps)
ch_mask |= ch_maps->ch_mask;

num_channels = ch_mask ? hweight_long(ch_mask) : params_channels(params);

if (num_channels != params_channels(params))
dev_dbg(sdev->dev, "configuring stream format for %d channels, params_channels was %d\n",
num_channels, params_channels(params));

bits = snd_hdac_stream_format_bits(params_format(params), SNDRV_PCM_SUBFORMAT_STD,
params_physical_width(params));

format_val = snd_hdac_stream_format(num_channels, bits, params_rate(params));
format_val = snd_hdac_stream_format(params_channels(params), bits, params_rate(params));

dev_dbg(sdev->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val,
params_rate(params), num_channels, params_format(params));
params_rate(params), params_channels(params), params_format(params));

return format_val;
}
Expand Down Expand Up @@ -454,28 +423,6 @@ static int hda_ipc4_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *c
return ret;
}

static struct hdac_ext_stream *sdw_hda_ipc4_get_hext_stream(struct snd_sof_dev *sdev,
struct snd_soc_dai *cpu_dai,
struct snd_pcm_substream *substream)
{
struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
struct snd_sof_widget *swidget = w->dobj.private;
struct snd_sof_dai *dai = swidget->private;
struct sof_ipc4_copier *ipc4_copier = dai->private;
struct sof_ipc4_alh_configuration_blob *blob;

blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config;

/*
* Starting with ACE_2_0, re-setting the device_count is mandatory to avoid using
* the multi-gateway firmware configuration. The DMA hardware can take care of
* multiple links without needing any firmware assistance
*/
blob->alh_cfg.device_count = 1;

return hda_ipc4_get_hext_stream(sdev, cpu_dai, substream);
}

static const struct hda_dai_widget_dma_ops hda_ipc4_dma_ops = {
.get_hext_stream = hda_ipc4_get_hext_stream,
.assign_hext_stream = hda_assign_hext_stream,
Expand Down Expand Up @@ -517,7 +464,7 @@ static const struct hda_dai_widget_dma_ops dmic_ipc4_dma_ops = {
};

static const struct hda_dai_widget_dma_ops sdw_ipc4_dma_ops = {
.get_hext_stream = sdw_hda_ipc4_get_hext_stream,
.get_hext_stream = hda_ipc4_get_hext_stream,
.assign_hext_stream = hda_assign_hext_stream,
.release_hext_stream = hda_release_hext_stream,
.setup_hext_stream = hda_setup_hext_stream,
Expand Down
44 changes: 35 additions & 9 deletions sound/soc/sof/intel/hda-dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,13 +347,16 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct sof_ipc4_dma_config_tlv *dma_config_tlv;
const struct hda_dai_widget_dma_ops *ops;
struct sof_ipc4_dma_config *dma_config;
struct sof_ipc4_copier *ipc4_copier;
struct hdac_ext_stream *hext_stream;
struct hdac_stream *hstream;
struct snd_sof_dev *sdev;
struct snd_soc_dai *dai;
int cpu_dai_id;
int stream_id;
int ret;

Expand Down Expand Up @@ -393,7 +396,12 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream,
/* configure TLV */
ipc4_copier = widget_to_copier(w);

dma_config_tlv = &ipc4_copier->dma_config_tlv;
for_each_rtd_cpu_dais(rtd, cpu_dai_id, dai) {
if (dai == cpu_dai)
break;
}

dma_config_tlv = &ipc4_copier->dma_config_tlv[cpu_dai_id];
dma_config_tlv->type = SOF_IPC4_GTW_DMA_CONFIG_ID;
/* dma_config_priv_size is zero */
dma_config_tlv->length = sizeof(dma_config_tlv->dma_config);
Expand All @@ -404,7 +412,11 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream,
dma_config->pre_allocated_by_host = 1;
dma_config->dma_channel_id = stream_id - 1;
dma_config->stream_id = stream_id;
dma_config->dma_stream_channel_map.device_count = 0; /* mapping not used */
/*
* Currently we use a DMA for each device in ALH blob. The device will
* be copied in sof_ipc4_prepare_copier_module.
*/
dma_config->dma_stream_channel_map.device_count = 1;
dma_config->dma_priv_config_size = 0;

skip_tlv:
Expand Down Expand Up @@ -441,16 +453,18 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct sof_ipc4_dma_config_tlv *dma_config_tlv;
const struct hda_dai_widget_dma_ops *ops;
struct snd_soc_dai_link_ch_map *ch_maps;
struct sof_ipc4_dma_config *dma_config;
struct sof_ipc4_copier *ipc4_copier;
struct hdac_ext_stream *hext_stream;
struct snd_soc_dai *dai;
struct snd_sof_dev *sdev;
bool cpu_dai_found = false;
int cpu_dai_id;
int ch_mask;
int ret;
int j;
int i;

ret = non_hda_dai_hw_params(substream, params, cpu_dai);
if (ret < 0) {
Expand Down Expand Up @@ -480,11 +494,7 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
if (!cpu_dai_found)
return -ENODEV;

ch_mask = 0;
for_each_link_ch_maps(rtd->dai_link, j, ch_maps) {
if (ch_maps->cpu == cpu_dai_id)
ch_mask |= ch_maps->ch_mask;
}
ch_mask = GENMASK(params_channels(params) - 1, 0);

ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id,
ch_mask,
Expand All @@ -496,6 +506,22 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
return ret;
}

ipc4_copier = widget_to_copier(w);
dma_config_tlv = &ipc4_copier->dma_config_tlv[cpu_dai_id];
dma_config = &dma_config_tlv->dma_config;
dma_config->dma_stream_channel_map.mapping[0].device = link_id << 8 | cpu_dai->id;
dma_config->dma_stream_channel_map.mapping[0].channel_mask = ch_mask;

/*
* copy the dma_config_tlv to all ipc4_copier in the same link. Because only one copier
* will be handled in sof_ipc4_prepare_copier_module.
*/
for_each_rtd_cpu_dais(rtd, i, dai) {
w = snd_soc_dai_get_widget(dai, substream->stream);
ipc4_copier = widget_to_copier(w);
memcpy(&ipc4_copier->dma_config_tlv[cpu_dai_id], dma_config_tlv,
sizeof(*dma_config_tlv));
}
return 0;
}
EXPORT_SYMBOL_NS(sdw_hda_dai_hw_params, SND_SOC_SOF_INTEL_HDA_COMMON);
Expand Down
44 changes: 30 additions & 14 deletions sound/soc/sof/ipc4-topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,11 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget)
}

ipc4_copier->copier_config = (uint32_t *)blob;
ipc4_copier->data.gtw_cfg.config_length = sizeof(*blob) >> 2;
/* set data.gtw_cfg.config_length based on device_count */
ipc4_copier->data.gtw_cfg.config_length = (sizeof(blob->gw_attr) +
sizeof(blob->alh_cfg.device_count) +
sizeof(*blob->alh_cfg.mapping) *
blob->alh_cfg.device_count) >> 2;
break;
}
case SOF_DAI_INTEL_SSP:
Expand Down Expand Up @@ -1463,6 +1467,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
u32 deep_buffer_dma_ms = 0;
int output_fmt_index;
bool single_output_format;
int i;

dev_dbg(sdev->dev, "copier %s, type %d", swidget->widget->name, swidget->id);

Expand Down Expand Up @@ -1680,6 +1685,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
*/
if (ipc4_copier->dai_type == SOF_DAI_INTEL_ALH) {
struct sof_ipc4_alh_configuration_blob *blob;
struct sof_ipc4_dma_config *dma_config;
struct sof_ipc4_copier_data *alh_data;
struct sof_ipc4_copier *alh_copier;
struct snd_sof_widget *w;
Expand All @@ -1688,7 +1694,6 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
u32 ch_map;
u32 step;
u32 mask;
int i;

blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config;

Expand Down Expand Up @@ -1720,6 +1725,18 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
alh_copier = (struct sof_ipc4_copier *)dai->private;
alh_data = &alh_copier->data;
blob->alh_cfg.mapping[i].device = alh_data->gtw_cfg.node_id;

/*
* The mapping[i] device in ALH blob should be the same as the
* dma_config_tlv[i] mapping device if a dma_config_tlv is present.
Copy link
Member

Choose a reason for hiding this comment

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

Is this really a requirement? this isn't something we discussed? I don't mind setting it to the same value as the DMA config TLV if the goal was to align with the other OS, but I would be surprised if the firmware used this value.

* The device id will be used for DMA tlv mapping purposes.
*/
if (ipc4_copier->dma_config_tlv[i].length) {
dma_config = &ipc4_copier->dma_config_tlv[i].dma_config;
blob->alh_cfg.mapping[i].device =
dma_config->dma_stream_channel_map.mapping[0].device;
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 understand this part. Do we actually care about the alh_cfg mapping? It seems completely redundant.

@iganakov do you actually use this for the aggregation or do you rely on the DMA TLV only?

}

/*
* Set the same channel mask for playback as the audio data is
* duplicated for all speakers. For capture, split the channels
Expand Down Expand Up @@ -1798,19 +1815,18 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
gtw_cfg_config_length = copier_data->gtw_cfg.config_length * 4;
ipc_size = sizeof(*copier_data) + gtw_cfg_config_length;

if (ipc4_copier->dma_config_tlv.type == SOF_IPC4_GTW_DMA_CONFIG_ID &&
ipc4_copier->dma_config_tlv.length) {
dma_config_tlv_size = sizeof(ipc4_copier->dma_config_tlv) +
ipc4_copier->dma_config_tlv.dma_config.dma_priv_config_size;

/* paranoia check on TLV size/length */
if (dma_config_tlv_size != ipc4_copier->dma_config_tlv.length +
sizeof(uint32_t) * 2) {
dev_err(sdev->dev, "Invalid configuration, TLV size %d length %d\n",
dma_config_tlv_size, ipc4_copier->dma_config_tlv.length);
return -EINVAL;
}
dma_config_tlv_size = 0;
for (i = 0; i < SOF_IPC4_DMA_DEVICE_MAX_COUNT; i++) {
if (ipc4_copier->dma_config_tlv[i].type != SOF_IPC4_GTW_DMA_CONFIG_ID)
continue;
dma_config_tlv_size += ipc4_copier->dma_config_tlv[i].length;
dma_config_tlv_size +=
ipc4_copier->dma_config_tlv[i].dma_config.dma_priv_config_size;
dma_config_tlv_size += (sizeof(ipc4_copier->dma_config_tlv[i]) -
sizeof(ipc4_copier->dma_config_tlv[i].dma_config));
}

if (dma_config_tlv_size) {
ipc_size += dma_config_tlv_size;

/* we also need to increase the size at the gtw level */
Expand Down
2 changes: 1 addition & 1 deletion sound/soc/sof/ipc4-topology.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ struct sof_ipc4_copier {
struct sof_ipc4_gtw_attributes *gtw_attr;
u32 dai_type;
int dai_index;
struct sof_ipc4_dma_config_tlv dma_config_tlv;
struct sof_ipc4_dma_config_tlv dma_config_tlv[SOF_IPC4_DMA_DEVICE_MAX_COUNT];
};

/**
Expand Down