From 7dc06d5feee7d72fb1d3415b58f492f2ec53a564 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Fri, 19 Jan 2024 15:26:23 +0800 Subject: [PATCH 01/12] Revert "ASoC: SOF: Intel: hda-dai-ops: reset device count for SoundWire DAIs" This reverts commit 699e146d9ebf42ee2a5d4e4e28f7a49c4aef0105. Don't reset device_count as we will use the multi-gateway firmware configuration. Signed-off-by: Bard Liao --- sound/soc/sof/intel/hda-dai-ops.c | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index e2da955ea7f526..fcd6023d8be991 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -454,28 +454,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, @@ -517,7 +495,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, From c6235d94bf112891cf26ef677e5d2a4f0372ad4e Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Fri, 29 Dec 2023 19:45:20 +0800 Subject: [PATCH 02/12] ASoC: SOF: make dma_config_tlv be an array Each stream needs a dma_config_tlv. We will handle multi dma_config_tlv in the follow up commits. Signed-off-by: Bard Liao --- sound/soc/sof/intel/hda-dai.c | 2 +- sound/soc/sof/ipc4-topology.c | 25 ++++++++++++------------- sound/soc/sof/ipc4-topology.h | 2 +- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 043888bdf0a627..ae42ea01b01003 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -393,7 +393,7 @@ 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; + dma_config_tlv = &ipc4_copier->dma_config_tlv[0]; 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); diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index d8c7fbe946ef95..2637abe9ff5d28 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1463,6 +1463,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); @@ -1688,7 +1689,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; @@ -1798,19 +1798,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 */ diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index dce174a190ddc6..aa5122c3721d3a 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -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]; }; /** From 32f9856d7c3fa52c6c912bc1f53e2296df95fcab Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Fri, 29 Dec 2023 20:24:33 +0800 Subject: [PATCH 03/12] ASoC: SOF: Intel: hda-dai: set dma_stream_channel_map device sof_ipc4_dma_config_tlv{} is required for ACE2.x. And the dma_stream_channel_map.mapping in sof_ipc4_dma_config{} should be the same as the mapping in sof_ipc4_alh_configuration_blob{}. The device id is equal to node_id which is 'node_type | stream_tag - 1', The purposes of device id is to map DMA tlv. The patch copies the mapping from sof_ipc4_alh_configuration_blob{} to sof_ipc4_dma_config_tlv{} to meet the firmware's requirement. Signed-off-by: Bard Liao --- sound/soc/sof/intel/hda-dai.c | 28 ++++++++++++++++++++++++++-- sound/soc/sof/ipc4-topology.c | 27 +++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index ae42ea01b01003..205807ebff205b 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -347,6 +347,7 @@ 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; @@ -354,8 +355,11 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream, 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; + int i; ops = hda_dai_get_ops(substream, cpu_dai); if (!ops) { @@ -393,7 +397,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[0]; + 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); @@ -404,9 +413,24 @@ 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; + /* + * 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)); + } + skip_tlv: return 0; } diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 2637abe9ff5d28..d0fa236f2c680c 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1681,6 +1681,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; @@ -1720,21 +1721,39 @@ 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 dma_config_tlv[i] mapping device should be the same as + * the mapping[i] device in ALH blob. The device id is used + * only for DMA tlv mapping purposes. + */ + dma_config = &ipc4_copier->dma_config_tlv[i].dma_config; + dma_config->dma_stream_channel_map.mapping[0].device = + blob->alh_cfg.mapping[i].device; + /* * Set the same channel mask for playback as the audio data is * duplicated for all speakers. For capture, split the channels * among the aggregated DAIs. For example, with 4 channels on 2 - * aggregated DAIs, the channel_mask should be 0x3 and 0xc for the - * two DAI's. + * aggregated DAIs, the channel_mask of alh_cfg.mapping + * should be 0x3 and 0xc for the two DAI's. However, the + * channel_mask of dma_stream_channel_map.mapping should be both + * 0x3 since we always use the lowest channels. * The channel masks used depend on the cpu_dais used in the * dailink at the machine driver level, which actually comes from * the tables in soc_acpi files depending on the _ADR and devID * registers for each codec. */ - if (w->id == snd_soc_dapm_dai_in) + if (w->id == snd_soc_dapm_dai_in) { blob->alh_cfg.mapping[i].channel_mask = ch_mask; - else + dma_config->dma_stream_channel_map.mapping[0].channel_mask = + ch_mask; + } else { blob->alh_cfg.mapping[i].channel_mask = mask << (step * i); + /* No need to shift for the channel_mask in dma_config */ + dma_config->dma_stream_channel_map.mapping[0].channel_mask = + mask; + } i++; } From 890f026804f3d30e0c2fcd4ae873c8956214aabd Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Mon, 29 Jan 2024 20:23:47 +0800 Subject: [PATCH 04/12] Revert "ASoC: SOF: Intel: hda-dai-ops: only allocate/release streams for first CPU DAI" This reverts commit f8ba62ac863c33fc0d8ac3f1270985c2b77f4377. The SoundWire aggregated solution was to use one DMA on multiple links. But, the solution changed to use one DMA for each link. It means that we should assign HDaudio stream_tag for each cpu_dai. Signed-off-by: Bard Liao --- sound/soc/sof/intel/hda-dai-ops.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index fcd6023d8be991..b96b36ba88ad08 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -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; @@ -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, From d394dc9d08fe1e3886c562df813a483d61807c5b Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 19 Dec 2023 19:16:25 +0800 Subject: [PATCH 05/12] ASoC: SOF: ipc4-topology: set config_length based on device_count Set ipc4_copier->data.gtw_cfg.config_length dynamically based on blob->alh_cfg.device_count to align with the other OS. Signed-off-by: Bard Liao --- sound/soc/sof/ipc4-topology.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index d0fa236f2c680c..196283d0b6c855 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -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: From 996e4aca2c3a350cf38728aa7ae630e004514b08 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Mon, 29 Jan 2024 14:58:57 +0800 Subject: [PATCH 06/12] Revert "ASoC: SOF: Intel: hda-dai-ops: fix HDaudio link format" This reverts commit 7f9512a31dc2a3737f1a78ab410d4d2c6ca6b8b2. commit 7f9512a31dc2 ("ASoC: SOF: Intel: hda-dai-ops: fix HDaudio link format") added up all DAIs channels for SoundWire aggregation mode. That was correct because we used a DMA for all DAIs. But, it is not valid anymore after we use a DMA for each DAI. Signed-off-by: Bard Liao --- sound/soc/sof/intel/hda-dai-ops.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index b96b36ba88ad08..01e5f0617ae5b9 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -226,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; } From 07b8e7e97fb5d2e83b8029868424258502fcc153 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Fri, 26 Jan 2024 18:08:44 +0800 Subject: [PATCH 07/12] ASoC: SOF: Intel: hda-dai: set lowest N bits in ch_mask We always use the lowest N channels of stream. So, set ch_mask to GENMASK(params_channels(params) - 1, 0). Signed-off-by: Bard Liao --- sound/soc/sof/intel/hda-dai.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 205807ebff205b..d9aac3f68828ed 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -466,7 +466,6 @@ 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); const struct hda_dai_widget_dma_ops *ops; - struct snd_soc_dai_link_ch_map *ch_maps; struct hdac_ext_stream *hext_stream; struct snd_soc_dai *dai; struct snd_sof_dev *sdev; @@ -474,7 +473,6 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, int cpu_dai_id; int ch_mask; int ret; - int j; ret = non_hda_dai_hw_params(substream, params, cpu_dai); if (ret < 0) { @@ -504,11 +502,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, From 96dc5bd5f34baec8ebdefac48c9c5177ac028a00 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 31 Jan 2024 17:41:30 +0100 Subject: [PATCH 08/12] soundwire: intel_ace2x: use legacy formula for intel_alh_id Starting with Lunar Lake, the notion of ALH is mostly irrelevant, since the HDaudio DMAs are used. However the firmware still relies on an 'ALH gateway' with a 'node_id' based on the same formula. This patch in isolation has no functional impact, it's only when the ASoC parts use it that we will see a changed behavior. Signed-off-by: Pierre-Louis Bossart --- drivers/soundwire/intel_ace2x.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/soundwire/intel_ace2x.c b/drivers/soundwire/intel_ace2x.c index f26d4e5c2c7ab7..771f5fcbbbc175 100644 --- a/drivers/soundwire/intel_ace2x.c +++ b/drivers/soundwire/intel_ace2x.c @@ -306,12 +306,16 @@ static int intel_hw_params(struct snd_pcm_substream *substream, dir = SDW_DATA_DIR_TX; pdi = sdw_cdns_alloc_pdi(cdns, &cdns->pcm, ch, dir, dai->id); - if (!pdi) { ret = -EINVAL; goto error; } + /* use same definitions for alh_id as previous generations */ + pdi->intel_alh_id = (sdw->instance * 16) + pdi->num + 3; + if (pdi->num >= 2) + pdi->intel_alh_id += 2; + /* the SHIM will be configured in the callback functions */ sdw_cdns_config_stream(cdns, ch, dir, pdi); From e01b9de91d6cf6fa4a7b6207ce184a96723645db Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 31 Jan 2024 17:47:02 +0100 Subject: [PATCH 09/12] ASoC: SOF: Intel: hda-dai: add helpers to set dai config We need to be able to set the dai config differently for SoundWire. Signed-off-by: Pierre-Louis Bossart --- sound/soc/sof/intel/hda-dai.c | 47 +++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index d9aac3f68828ed..7337c471d2fea1 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -222,15 +222,15 @@ static int __maybe_unused hda_dai_hw_free(struct snd_pcm_substream *substream, return hda_link_dma_cleanup(substream, hext_stream, cpu_dai); } -static int __maybe_unused hda_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) +static int __maybe_unused hda_dai_hw_params_data(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai, + struct snd_sof_dai_config_data *data, + unsigned int flags) { struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); struct hdac_ext_stream *hext_stream; - struct snd_sof_dai_config_data data = { 0 }; - unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; struct snd_sof_dev *sdev = widget_to_sdev(w); int ret; @@ -250,9 +250,19 @@ static int __maybe_unused hda_dai_hw_params(struct snd_pcm_substream *substream, hext_stream = ops->get_hext_stream(sdev, dai, substream); flags |= SOF_DAI_CONFIG_FLAGS_2_STEP_STOP << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT; - data.dai_data = hdac_stream(hext_stream)->stream_tag - 1; + data->dai_data = hdac_stream(hext_stream)->stream_tag - 1; + + return hda_dai_config(w, flags, data); +} + +static int __maybe_unused hda_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_sof_dai_config_data data = { 0 }; + unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; - return hda_dai_config(w, flags, &data); + return hda_dai_hw_params_data(substream, params, dai, &data, flags); } /* @@ -342,9 +352,11 @@ static struct sof_ipc4_copier *widget_to_copier(struct snd_soc_dapm_widget *w) return ipc4_copier; } -static int non_hda_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *cpu_dai) +static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *cpu_dai, + struct snd_sof_dai_config_data *data, + unsigned int flags) { 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); @@ -435,6 +447,16 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream, return 0; } +static int non_hda_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *cpu_dai) +{ + struct snd_sof_dai_config_data data = { 0 }; + unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; + + return non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags); +} + static int non_hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { @@ -465,6 +487,8 @@ 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 snd_sof_dai_config_data data = { 0 }; + unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; const struct hda_dai_widget_dma_ops *ops; struct hdac_ext_stream *hext_stream; struct snd_soc_dai *dai; @@ -474,7 +498,8 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, int ch_mask; int ret; - ret = non_hda_dai_hw_params(substream, params, cpu_dai); + data.dai_index = (link_id << 8) | cpu_dai->id; + ret = non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags); if (ret < 0) { dev_err(cpu_dai->dev, "%s: non_hda_dai_hw_params failed %d\n", __func__, ret); return ret; From 2546f6fa01037369cc4b6a7d3db3967daaf1fd23 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 31 Jan 2024 17:53:40 +0100 Subject: [PATCH 10/12] ASoC: SOF: Intel: hda: extend signature of sdw_hda_dai_hw_params() Add intel_alh_id to set the expected gateway node_id in a follow-up patch. Signed-off-by: Pierre-Louis Bossart --- sound/soc/sof/intel/hda-dai.c | 3 ++- sound/soc/sof/intel/hda.c | 3 ++- sound/soc/sof/intel/hda.h | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 7337c471d2fea1..397398bc530383 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -483,7 +483,8 @@ static const struct snd_soc_dai_ops dmic_dai_ops = { int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai, - int link_id) + int link_id, + int intel_alh_id) { 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); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index d6d9c61f10ad16..b2f9c556cc50aa 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -77,7 +77,8 @@ static int sdw_ace2x_params_stream(struct device *dev, return sdw_hda_dai_hw_params(params_data->substream, params_data->hw_params, params_data->dai, - params_data->link_id); + params_data->link_id, + params_data->alh_stream_id); } static int sdw_ace2x_free_stream(struct device *dev, diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 0156d866e3b225..c3c342c2b7cb50 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -866,7 +866,8 @@ static inline bool hda_common_check_sdw_irq(struct snd_sof_dev *sdev) int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai, - int link_id); + int link_id, + int intel_alh_id); int sdw_hda_dai_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai, From 5dce0e21b2ad91280978852e64e2df706e6296bf Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 31 Jan 2024 17:59:58 +0100 Subject: [PATCH 11/12] ASoC: SOF: IPC4: extend dai_data with node_id The node_id value needs to be handled specifically for ALH. Signed-off-by: Pierre-Louis Bossart --- sound/soc/sof/intel/hda-dai.c | 1 + sound/soc/sof/intel/hda.c | 1 + sound/soc/sof/ipc4-topology.c | 2 +- sound/soc/sof/sof-audio.h | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 397398bc530383..e3377ec0638b25 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -500,6 +500,7 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, int ret; data.dai_index = (link_id << 8) | cpu_dai->id; + data.dai_node_id = intel_alh_id; ret = non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags); if (ret < 0) { dev_err(cpu_dai->dev, "%s: non_hda_dai_hw_params failed %d\n", __func__, ret); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index b2f9c556cc50aa..66126fb31d52db 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -63,6 +63,7 @@ static int sdw_params_stream(struct device *dev, data.dai_index = (params_data->link_id << 8) | d->id; data.dai_data = params_data->alh_stream_id; + data.dai_node_id = data.dai_data; return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_PARAMS, &data); } diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 196283d0b6c855..ad2cbe6c988e5b 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -2853,7 +2853,7 @@ static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * */ if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) { copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; - copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_data); + copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_node_id); } break; case SOF_DAI_INTEL_DMIC: diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 9ea2ac5adac79e..fd664d5586f0d5 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -91,6 +91,7 @@ struct snd_sof_pcm; struct snd_sof_dai_config_data { int dai_index; int dai_data; /* contains DAI-specific information */ + int dai_node_id; /* contains DAI-specific information for Gateway configuration */ }; /** From 231d1a73d3527a22ffbafc54cd108a79fc02ac86 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 31 Jan 2024 18:10:25 +0100 Subject: [PATCH 12/12] ASoC: SOF: Intel: set the DMA TLV device as dai_index The firmware does not really care about the exact values used for the DMA TLV 'device' field, the only requirement is that each DMA TLV contains a unique number. In practice, there's no need to be creative, so this patch uses the same conventions used by reference firmware and the other OS. Signed-off-by: Pierre-Louis Bossart --- sound/soc/sof/intel/hda-dai.c | 4 ++-- sound/soc/sof/ipc4-topology.c | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index e3377ec0638b25..9c27cabf7d6ab3 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -426,10 +426,10 @@ static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream, dma_config->dma_channel_id = stream_id - 1; dma_config->stream_id = stream_id; /* - * Currently we use a DMA for each device in ALH blob. The device will - * be copied in sof_ipc4_prepare_copier_module. + * Currently we use a DMA for each device in ALH blob. */ dma_config->dma_stream_channel_map.device_count = 1; + dma_config->dma_stream_channel_map.mapping[0].device = data->dai_index; dma_config->dma_priv_config_size = 0; /* diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index ad2cbe6c988e5b..6c9c675941c304 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1726,11 +1726,6 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, alh_data = &alh_copier->data; blob->alh_cfg.mapping[i].device = alh_data->gtw_cfg.node_id; - /* - * The dma_config_tlv[i] mapping device should be the same as - * the mapping[i] device in ALH blob. The device id is used - * only for DMA tlv mapping purposes. - */ dma_config = &ipc4_copier->dma_config_tlv[i].dma_config; dma_config->dma_stream_channel_map.mapping[0].device = blob->alh_cfg.mapping[i].device;