From 3858464de57b77db51f83e3831950cf18a6aff28 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 13 Feb 2024 12:12:33 +0200 Subject: [PATCH 01/15] ASoC: SOF: ipc4-topology: change chain_dma handling in dai_config The chain_dma mode is currently only handled for HDaudio, but can be used for orther DAIs starting with LunarLake. Move the chain_dma handling earlier. Error detection for the chain_dma case for older platforms is handled at a different level. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://msgid.link/r/20240213101247.28887-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index f779156fe0e6..8ac35e6df75f 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -2796,13 +2796,14 @@ static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * if (!data) return 0; + if (pipeline->use_chain_dma) { + pipeline->msg.primary &= ~SOF_IPC4_GLB_CHAIN_DMA_LINK_ID_MASK; + pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_LINK_ID(data->dai_data); + return 0; + } + switch (ipc4_copier->dai_type) { case SOF_DAI_INTEL_HDA: - if (pipeline->use_chain_dma) { - pipeline->msg.primary &= ~SOF_IPC4_GLB_CHAIN_DMA_LINK_ID_MASK; - pipeline->msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_LINK_ID(data->dai_data); - break; - } gtw_attr = ipc4_copier->gtw_attr; gtw_attr->lp_buffer_alloc = pipeline->lp_mode; fallthrough; From ba91d0919a78d344d19b02a3899d0921b2f903d1 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 13 Feb 2024 12:12:34 +0200 Subject: [PATCH 02/15] ASoC: SOF: ops: add new 'is_chain_dma_supported' callback IPC4 introduced a 'chain-dma' mode when host and link DMA are connected by firmware without using a regular pipeline or the ability to add intermediate connections. This mode is not available on all platforms and all links, so add a platform-specific callback to help the SOF ipc4-topology core handle different hardware+firmware configurations. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://msgid.link/r/20240213101247.28887-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ops.h | 9 +++++++++ sound/soc/sof/sof-priv.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index 6538d9f4fe96..6cf21e829e07 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -567,6 +567,15 @@ snd_sof_set_mach_params(struct snd_soc_acpi_mach *mach, sof_ops(sdev)->set_mach_params(mach, sdev); } +static inline bool +snd_sof_is_chain_dma_supported(struct snd_sof_dev *sdev, u32 dai_type) +{ + if (sof_ops(sdev) && sof_ops(sdev)->is_chain_dma_supported) + return sof_ops(sdev)->is_chain_dma_supported(sdev, dai_type); + + return false; +} + /** * snd_sof_dsp_register_poll_timeout - Periodically poll an address * until a condition is met or a timeout occurs diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 6d7897bf9607..6c163c008607 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -338,6 +338,8 @@ struct snd_sof_dsp_ops { struct snd_soc_dai_driver *drv; int num_drv; + bool (*is_chain_dma_supported)(struct snd_sof_dev *sdev, u32 dai_type); /* optional */ + /* ALSA HW info flags, will be stored in snd_pcm_runtime.hw.info */ u32 hw_info; From d69f9ecbe1ecfa97b9c8ab7b6332bd73ba2ff4d8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 13 Feb 2024 12:12:35 +0200 Subject: [PATCH 03/15] ASoC: SOF: Intel: hda: add 'is_chain_dma_supported' callback Reuse existing function to get the interface mask and expose it to the SOF core with a callback - the main user is the IPC4 topology so only HDaudio platforms provide this callback. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://msgid.link/r/20240213101247.28887-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-common-ops.c | 1 + sound/soc/sof/intel/hda.c | 63 ++++++++++++++++++++++------ sound/soc/sof/intel/hda.h | 5 +++ sound/soc/sof/sof-priv.h | 7 ++++ 4 files changed, 64 insertions(+), 12 deletions(-) diff --git a/sound/soc/sof/intel/hda-common-ops.c b/sound/soc/sof/intel/hda-common-ops.c index 26105d8f1bdc..2b385cddc385 100644 --- a/sound/soc/sof/intel/hda-common-ops.c +++ b/sound/soc/sof/intel/hda-common-ops.c @@ -83,6 +83,7 @@ struct snd_sof_dsp_ops sof_hda_common_ops = { /* DAI drivers */ .drv = skl_dai, .num_drv = SOF_SKL_NUM_DAIS, + .is_chain_dma_supported = hda_is_chain_dma_supported, /* PM */ .suspend = hda_dsp_suspend, diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index fe4ae349dad5..0bae439feb8b 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -46,44 +46,83 @@ #define EXCEPT_MAX_HDR_SIZE 0x400 #define HDA_EXT_ROM_STATUS_SIZE 8 -static u32 hda_get_interface_mask(struct snd_sof_dev *sdev) +static void hda_get_interfaces(struct snd_sof_dev *sdev, u32 *interface_mask) { const struct sof_intel_dsp_desc *chip; - u32 interface_mask[2] = { 0 }; chip = get_chip_info(sdev->pdata); switch (chip->hw_ip_version) { case SOF_INTEL_TANGIER: case SOF_INTEL_BAYTRAIL: case SOF_INTEL_BROADWELL: - interface_mask[0] = BIT(SOF_DAI_INTEL_SSP); + interface_mask[SOF_DAI_DSP_ACCESS] = BIT(SOF_DAI_INTEL_SSP); break; case SOF_INTEL_CAVS_1_5: case SOF_INTEL_CAVS_1_5_PLUS: - interface_mask[0] = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | - BIT(SOF_DAI_INTEL_HDA); - interface_mask[1] = BIT(SOF_DAI_INTEL_HDA); + interface_mask[SOF_DAI_DSP_ACCESS] = + BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | BIT(SOF_DAI_INTEL_HDA); + interface_mask[SOF_DAI_HOST_ACCESS] = BIT(SOF_DAI_INTEL_HDA); break; case SOF_INTEL_CAVS_1_8: case SOF_INTEL_CAVS_2_0: case SOF_INTEL_CAVS_2_5: case SOF_INTEL_ACE_1_0: - interface_mask[0] = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | - BIT(SOF_DAI_INTEL_HDA) | BIT(SOF_DAI_INTEL_ALH); - interface_mask[1] = BIT(SOF_DAI_INTEL_HDA); + interface_mask[SOF_DAI_DSP_ACCESS] = + BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | + BIT(SOF_DAI_INTEL_HDA) | BIT(SOF_DAI_INTEL_ALH); + interface_mask[SOF_DAI_HOST_ACCESS] = BIT(SOF_DAI_INTEL_HDA); break; case SOF_INTEL_ACE_2_0: - interface_mask[0] = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | - BIT(SOF_DAI_INTEL_HDA) | BIT(SOF_DAI_INTEL_ALH); - interface_mask[1] = interface_mask[0]; /* all interfaces accessible without DSP */ + interface_mask[SOF_DAI_DSP_ACCESS] = + BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | + BIT(SOF_DAI_INTEL_HDA) | BIT(SOF_DAI_INTEL_ALH); + /* all interfaces accessible without DSP */ + interface_mask[SOF_DAI_HOST_ACCESS] = + interface_mask[SOF_DAI_DSP_ACCESS]; break; default: break; } +} + +static u32 hda_get_interface_mask(struct snd_sof_dev *sdev) +{ + u32 interface_mask[SOF_DAI_ACCESS_NUM] = { 0 }; + + hda_get_interfaces(sdev, interface_mask); return interface_mask[sdev->dspless_mode_selected]; } +bool hda_is_chain_dma_supported(struct snd_sof_dev *sdev, u32 dai_type) +{ + u32 interface_mask[SOF_DAI_ACCESS_NUM] = { 0 }; + const struct sof_intel_dsp_desc *chip; + + if (sdev->dspless_mode_selected) + return false; + + hda_get_interfaces(sdev, interface_mask); + + if (!(interface_mask[SOF_DAI_DSP_ACCESS] & BIT(dai_type))) + return false; + + if (dai_type == SOF_DAI_INTEL_HDA) + return true; + + switch (dai_type) { + case SOF_DAI_INTEL_SSP: + case SOF_DAI_INTEL_DMIC: + case SOF_DAI_INTEL_ALH: + chip = get_chip_info(sdev->pdata); + if (chip->hw_ip_version < SOF_INTEL_ACE_2_0) + return false; + return true; + default: + return false; + } +} + #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) /* diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 1592e27bc14d..b36eb7c78913 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -573,6 +573,11 @@ struct sof_intel_hda_stream { #define SOF_STREAM_SD_OFFSET_CRST 0x1 +/* + * DAI support + */ +bool hda_is_chain_dma_supported(struct snd_sof_dev *sdev, u32 dai_type); + /* * DSP Core services. */ diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 6c163c008607..5e5c5a36c3c9 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -157,6 +157,13 @@ struct sof_firmware { u32 payload_offset; }; +enum sof_dai_access { + SOF_DAI_DSP_ACCESS, /* access from DSP only */ + SOF_DAI_HOST_ACCESS, /* access from host only */ + + SOF_DAI_ACCESS_NUM +}; + /* * SOF DSP HW abstraction operations. * Used to abstract DSP HW architecture and any IO busses between host CPU From a5b7767723e739c700f5c56841790a85bd7f13ae Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 13 Feb 2024 12:12:36 +0200 Subject: [PATCH 04/15] ASoC: SOF: Intel: hda-dai-ops: enable chain_dma for ALH Use the existing callbacks and mix/match of HDaudio and SoundWire support. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://msgid.link/r/20240213101247.28887-5-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai-ops.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index 55ce75db23e5..f58539d2f937 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -522,6 +522,17 @@ static const struct hda_dai_widget_dma_ops hda_ipc4_chain_dma_ops = { .get_hlink = hda_get_hlink, }; +static const struct hda_dai_widget_dma_ops sdw_ipc4_chain_dma_ops = { + .get_hext_stream = hda_get_hext_stream, + .assign_hext_stream = hda_assign_hext_stream, + .release_hext_stream = hda_release_hext_stream, + .setup_hext_stream = hda_setup_hext_stream, + .reset_hext_stream = hda_reset_hext_stream, + .trigger = hda_trigger, + .calc_stream_format = generic_calc_stream_format, + .get_hlink = sdw_get_hlink, +}; + static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, struct snd_pcm_substream *substream, int cmd) { @@ -620,6 +631,8 @@ hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidg } case SOF_IPC_TYPE_4: { + struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; + struct sof_ipc4_pipeline *pipeline = pipe_widget->private; struct sof_ipc4_copier *ipc4_copier = sdai->private; const struct sof_intel_dsp_desc *chip; @@ -627,15 +640,10 @@ hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidg switch (ipc4_copier->dai_type) { case SOF_DAI_INTEL_HDA: - { - struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; - struct sof_ipc4_pipeline *pipeline = pipe_widget->private; - if (pipeline->use_chain_dma) return &hda_ipc4_chain_dma_ops; return &hda_ipc4_dma_ops; - } case SOF_DAI_INTEL_SSP: if (chip->hw_ip_version < SOF_INTEL_ACE_2_0) return NULL; @@ -647,6 +655,8 @@ hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidg case SOF_DAI_INTEL_ALH: if (chip->hw_ip_version < SOF_INTEL_ACE_2_0) return NULL; + if (pipeline->use_chain_dma) + return &sdw_ipc4_chain_dma_ops; return &sdw_ipc4_dma_ops; default: From 426476344f01096c7dae6c5413cc8a8d9bbdea29 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 13 Feb 2024 12:12:37 +0200 Subject: [PATCH 05/15] ASoC: SOF: ipc4: store number of playback/capture streams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CHAIN_DMA IPC needs the number of playback streams as a start offset for the dma_id of a capture stream. This offset can be retrieved on Intel platforms from the GCAP information, and stored in the sof_ipc4_fw_data structure. One could argue that the fields added are not really dependent on any firmware definitions but rather on hardware capabilities, but they are required for the IPC CHAIN_DMA definitions so adding them in ipc4_fw_data isn't completely silly. The CHAIN_DMA IPC is currently only functional on Intel HDaudio DMAs, and gated by the snd_sof_is_chain_dma_supported() helper. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://msgid.link/r/20240213101247.28887-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-stream.c | 9 +++++++++ sound/soc/sof/ipc4-priv.h | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index f2ebadbbcc10..b387b1a69d7e 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -21,6 +21,7 @@ #include #include "../ops.h" #include "../sof-audio.h" +#include "../ipc4-priv.h" #include "hda.h" #define HDA_LTRP_GB_VALUE_US 95 @@ -937,6 +938,14 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) /* store total stream count (playback + capture) from GCAP */ sof_hda->stream_max = num_total; + /* store stream count from GCAP required for CHAIN_DMA */ + if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) { + struct sof_ipc4_fw_data *ipc4_data = sdev->private; + + ipc4_data->num_playback_streams = num_playback; + ipc4_data->num_capture_streams = num_capture; + } + return 0; } diff --git a/sound/soc/sof/ipc4-priv.h b/sound/soc/sof/ipc4-priv.h index 1d39836d5efa..f3b908b093f9 100644 --- a/sound/soc/sof/ipc4-priv.h +++ b/sound/soc/sof/ipc4-priv.h @@ -66,6 +66,8 @@ struct sof_ipc4_fw_library { * @nhlt: NHLT table either from the BIOS or the topology manifest * @mtrace_type: mtrace type supported on the booted platform * @mtrace_log_bytes: log bytes as reported by the firmware via fw_config reply + * @num_playback_streams: max number of playback DMAs, needed for CHAIN_DMA offset + * @num_capture_streams: max number of capture DMAs * @max_num_pipelines: max number of pipelines * @max_libs_count: Maximum number of libraries support by the FW including the * base firmware @@ -79,6 +81,8 @@ struct sof_ipc4_fw_data { void *nhlt; enum sof_ipc4_mtrace_type mtrace_type; u32 mtrace_log_bytes; + int num_playback_streams; + int num_capture_streams; int max_num_pipelines; u32 max_libs_count; bool fw_context_save; From 8722d245a73ff32491bff390136367ec223e2906 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 13 Feb 2024 12:12:38 +0200 Subject: [PATCH 06/15] ASoC: SOF: ipc4-pcm: fix dma_id for CHAIN_DMA capture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The existing code uses (stream_tag - 1) for the host and link dma id. This is correct for playback, but for capture this results in an invalid dma_type being used. The firmware assumes that the dma_id for capture is always larger than DAI_NUM_HDA_OUT This patch adds the offset for num_playback_streams, filled on Intel platforms with the value extracted from the hardware capabilities. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://msgid.link/r/20240213101247.28887-7-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-pcm.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index 85d3f390e4b2..035c44ce6c9d 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -231,9 +231,11 @@ sof_ipc4_update_pipeline_state(struct snd_sof_dev *sdev, int state, int cmd, */ static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev, + int direction, struct snd_sof_pcm_stream_pipeline_list *pipeline_list, int state, int cmd) { + struct sof_ipc4_fw_data *ipc4_data = sdev->private; bool allocate, enable, set_fifo_size; struct sof_ipc4_msg msg = {{ 0 }}; int i; @@ -294,6 +296,20 @@ static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev, msg.extension |= pipeline->msg.extension; } + if (direction == SNDRV_PCM_STREAM_CAPTURE) { + /* + * For ChainDMA the DMA ids are unique with the following mapping: + * playback: 0 - (num_playback_streams - 1) + * capture: num_playback_streams - (num_playback_streams + + * num_capture_streams - 1) + * + * Add the num_playback_streams offset to the DMA ids stored in + * msg.primary in case capture + */ + msg.primary += SOF_IPC4_GLB_CHAIN_DMA_HOST_ID(ipc4_data->num_playback_streams); + msg.primary += SOF_IPC4_GLB_CHAIN_DMA_LINK_ID(ipc4_data->num_playback_streams); + } + if (allocate) msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_ALLOCATE_MASK; @@ -340,7 +356,8 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component, * trigger function that handles the rest for the substream. */ if (pipeline->use_chain_dma) - return sof_ipc4_chain_dma_trigger(sdev, pipeline_list, state, cmd); + return sof_ipc4_chain_dma_trigger(sdev, substream->stream, + pipeline_list, state, cmd); /* allocate memory for the pipeline data */ trigger_list = kzalloc(struct_size(trigger_list, pipeline_instance_ids, From df82dbb5fb28a762113fc6d98985d36ef7785e32 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 13 Feb 2024 12:12:39 +0200 Subject: [PATCH 07/15] ASoC: SOF: ipc4-topology: allow chain_dma for all supported DAIs Now that we have a 'is_chain_dma_supported' callback we can use it to double-check possible disconnects between a topology file enabling chain-dma for a DAI and the hardware/firmware capabilities. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Rander Wang Signed-off-by: Peter Ujfalusi Link: https://msgid.link/r/20240213101247.28887-8-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 8ac35e6df75f..98e2f83b1c09 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -509,6 +509,7 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) { struct sof_ipc4_available_audio_format *available_fmt; struct snd_soc_component *scomp = swidget->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_sof_dai *dai = swidget->private; struct sof_ipc4_copier *ipc4_copier; struct snd_sof_widget *pipe_widget; @@ -552,10 +553,11 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) pipe_widget = swidget->spipe->pipe_widget; pipeline = pipe_widget->private; - if (pipeline->use_chain_dma && ipc4_copier->dai_type != SOF_DAI_INTEL_HDA) { - dev_err(scomp->dev, - "Bad DAI type '%d', Chained DMA is only supported by HDA DAIs (%d).\n", - ipc4_copier->dai_type, SOF_DAI_INTEL_HDA); + + if (pipeline->use_chain_dma && + !snd_sof_is_chain_dma_supported(sdev, ipc4_copier->dai_type)) { + dev_err(scomp->dev, "Bad DAI type '%d', Chain DMA is not supported\n", + ipc4_copier->dai_type); ret = -ENODEV; goto free_available_fmt; } From daa09d0615ce9c781777802874cffa4380f883c3 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 13 Feb 2024 12:12:40 +0200 Subject: [PATCH 08/15] ASoC: SOF: Intel: hda-dai: remove dspless special case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The existing code forces a parameter to be NULL but that parameter is not used yet. Remove the special case in preparation for additional changes. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://msgid.link/r/20240213101247.28887-9-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index f4cbc0ad5de3..4bffd9ea21a9 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -83,12 +83,8 @@ hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai sdev = widget_to_sdev(w); - /* - * The swidget parameter of hda_select_dai_widget_ops() is ignored in - * case of DSPless mode - */ if (sdev->dspless_mode_selected) - return hda_select_dai_widget_ops(sdev, NULL); + return hda_select_dai_widget_ops(sdev, swidget); sdai = swidget->private; From 743eb6c68d3534e01e73d316ddcaa7334c0e29d3 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 13 Feb 2024 12:12:41 +0200 Subject: [PATCH 09/15] ASoC: SOF: topology: dynamically allocate and store DAI widget->private MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For dspless mode, we need to allocate and store an 'sdai' structure. The existing code allocate the data on the stack and does not set the widget->private pointer. This minor change should not have any impact on existing DAIs, even when the DSP is used. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://msgid.link/r/20240213101247.28887-10-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-audio.c | 8 +++----- sound/soc/sof/topology.c | 13 ++++++++++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 9163975c9c3f..e693dcb475e4 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -46,7 +46,6 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev, { const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); struct snd_sof_pipeline *spipe = swidget->spipe; - struct snd_sof_widget *pipe_widget; int err = 0; int ret; @@ -59,8 +58,6 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev, if (--swidget->use_count) return 0; - pipe_widget = swidget->spipe->pipe_widget; - /* reset route setup status for all routes that contain this widget */ sof_reset_route_setup_status(sdev, swidget); @@ -109,8 +106,9 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev, * free the scheduler widget (same as pipe_widget) associated with the current swidget. * skip for static pipelines */ - if (swidget->dynamic_pipeline_widget && swidget->id != snd_soc_dapm_scheduler) { - ret = sof_widget_free_unlocked(sdev, pipe_widget); + if (swidget->spipe && swidget->dynamic_pipeline_widget && + swidget->id != snd_soc_dapm_scheduler) { + ret = sof_widget_free_unlocked(sdev, swidget->spipe->pipe_widget); if (ret < 0 && !err) err = ret; } diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 25fb0d1443b6..915c2e88e32b 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2356,23 +2356,29 @@ static int sof_dspless_widget_ready(struct snd_soc_component *scomp, int index, if (WIDGET_IS_DAI(w->id)) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_sof_widget *swidget; - struct snd_sof_dai dai; + struct snd_sof_dai *sdai; int ret; swidget = kzalloc(sizeof(*swidget), GFP_KERNEL); if (!swidget) return -ENOMEM; - memset(&dai, 0, sizeof(dai)); + sdai = kzalloc(sizeof(*sdai), GFP_KERNEL); + if (!sdai) { + kfree(swidget); + return -ENOMEM; + } - ret = sof_connect_dai_widget(scomp, w, tw, &dai); + ret = sof_connect_dai_widget(scomp, w, tw, sdai); if (ret) { kfree(swidget); + kfree(sdai); return ret; } swidget->scomp = scomp; swidget->widget = w; + swidget->private = sdai; mutex_init(&swidget->setup_mutex); w->dobj.private = swidget; list_add(&swidget->list, &sdev->widget_list); @@ -2396,6 +2402,7 @@ static int sof_dspless_widget_unload(struct snd_soc_component *scomp, /* remove and free swidget object */ list_del(&swidget->list); + kfree(swidget->private); kfree(swidget); } From 67bde2e8c0e4702911dd614d80127e098521a83c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 13 Feb 2024 12:12:42 +0200 Subject: [PATCH 10/15] ASoC: SOF: Intel: start SoundWire links earlier for LNL+ devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SoundWire integration is different from previous platforms, with no dependencies on the DSP enablement. We can start the SoundWire links in the probe instead of waiting for the post_fw_run stage. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://msgid.link/r/20240213101247.28887-11-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 5 +++++ sound/soc/sof/intel/hda.c | 17 +++++++++++++++++ sound/soc/sof/intel/lnl.c | 15 ++++++++++++++- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 2445ae7f6b2e..31ffa1a8f2ac 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -748,6 +748,7 @@ skip_dsp: static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume) { + const struct sof_intel_dsp_desc *chip; int ret; /* display codec must be powered before link reset */ @@ -780,6 +781,10 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume) hda_dsp_ctrl_ppcap_int_enable(sdev, true); } + chip = get_chip_info(sdev->pdata); + if (chip && chip->hw_ip_version >= SOF_INTEL_ACE_2_0) + hda_sdw_int_enable(sdev, true); + cleanup: /* display codec can powered off after controller init */ hda_codec_i915_display_power(sdev, false); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 0bae439feb8b..7fe72b065451 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1231,6 +1231,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) { struct pci_dev *pci = to_pci_dev(sdev->dev); struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; + const struct sof_intel_dsp_desc *chip; int ret = 0; hdev->dmic_dev = platform_device_register_data(sdev->dev, "dmic-codec", @@ -1344,12 +1345,28 @@ skip_dsp_setup: INIT_DELAYED_WORK(&hdev->d0i3_work, hda_dsp_d0i3_work); } + chip = get_chip_info(sdev->pdata); + if (chip && chip->hw_ip_version >= SOF_INTEL_ACE_2_0) { + ret = hda_sdw_startup(sdev); + if (ret < 0) { + dev_err(sdev->dev, "could not startup SoundWire links\n"); + goto disable_pp_cap; + } + + hda_sdw_int_enable(sdev, true); + } + init_waitqueue_head(&hdev->waitq); hdev->nhlt = intel_nhlt_init(sdev->dev); return 0; +disable_pp_cap: + if (!sdev->dspless_mode_selected) { + hda_dsp_ctrl_ppcap_int_enable(sdev, false); + hda_dsp_ctrl_ppcap_enable(sdev, false); + } free_ipc_irq: free_irq(sdev->ipc_irq, sdev); free_irq_vector: diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c index 30712ea05a7a..b2ade2741dce 100644 --- a/sound/soc/sof/intel/lnl.c +++ b/sound/soc/sof/intel/lnl.c @@ -77,6 +77,19 @@ static int lnl_hda_dsp_runtime_resume(struct snd_sof_dev *sdev) return hdac_bus_offload_dmic_ssp(sof_to_bus(sdev)); } +static int lnl_dsp_post_fw_run(struct snd_sof_dev *sdev) +{ + if (sdev->first_boot) { + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; + + /* Check if IMR boot is usable */ + if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT)) + hda->imrboot_supported = true; + } + + return 0; +} + int sof_lnl_ops_init(struct snd_sof_dev *sdev) { struct sof_ipc4_fw_data *ipc4_data; @@ -106,7 +119,7 @@ int sof_lnl_ops_init(struct snd_sof_dev *sdev) /* pre/post fw run */ sof_lnl_ops.pre_fw_run = mtl_dsp_pre_fw_run; - sof_lnl_ops.post_fw_run = mtl_dsp_post_fw_run; + sof_lnl_ops.post_fw_run = lnl_dsp_post_fw_run; /* parse platform specific extended manifest */ sof_lnl_ops.parse_platform_ext_manifest = NULL; From f9618ff105a0f6f5a6beed3edc557ea6a7d26df6 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 13 Feb 2024 12:12:43 +0200 Subject: [PATCH 11/15] ASoC: SOF: topology: Parse DAI type token for dspless mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Starting with LunarLake, the dspless mode can handle SoundWire/ALH, DMIC and SSPs, so we need to identify the dai type from topology. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://msgid.link/r/20240213101247.28887-12-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 1 + sound/soc/sof/sof-audio.h | 1 + sound/soc/sof/topology.c | 12 ++++++++++++ 3 files changed, 14 insertions(+) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 98e2f83b1c09..43d4abd79f44 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -549,6 +549,7 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) dev_dbg(scomp->dev, "dai %s node_type %u dai_type %u dai_index %d\n", swidget->widget->name, node_type, ipc4_copier->dai_type, ipc4_copier->dai_index); + dai->type = ipc4_copier->dai_type; ipc4_copier->data.gtw_cfg.node_id = SOF_IPC4_NODE_TYPE(node_type); pipe_widget = swidget->spipe->pipe_widget; diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index f98242a404db..9ea2ac5adac7 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -514,6 +514,7 @@ struct snd_sof_route { struct snd_sof_dai { struct snd_soc_component *scomp; const char *name; + u32 type; int number_configs; int current_config; diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 915c2e88e32b..bcdb499c96a0 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2354,7 +2354,10 @@ static int sof_dspless_widget_ready(struct snd_soc_component *scomp, int index, struct snd_soc_tplg_dapm_widget *tw) { if (WIDGET_IS_DAI(w->id)) { + static const struct sof_topology_token dai_tokens[] = { + {SOF_TKN_DAI_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_dai_type, 0}}; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct snd_soc_tplg_private *priv = &tw->priv; struct snd_sof_widget *swidget; struct snd_sof_dai *sdai; int ret; @@ -2369,6 +2372,15 @@ static int sof_dspless_widget_ready(struct snd_soc_component *scomp, int index, return -ENOMEM; } + ret = sof_parse_tokens(scomp, &sdai->type, dai_tokens, ARRAY_SIZE(dai_tokens), + priv->array, le32_to_cpu(priv->size)); + if (ret < 0) { + dev_err(scomp->dev, "Failed to parse DAI tokens for %s\n", tw->name); + kfree(swidget); + kfree(sdai); + return ret; + } + ret = sof_connect_dai_widget(scomp, w, tw, sdai); if (ret) { kfree(swidget); From 797b92591a236ac370257c1e742f6fd394993db5 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 13 Feb 2024 12:12:44 +0200 Subject: [PATCH 12/15] ASoC: SOF: Intel: hda-dai-ops: use dai_type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we have the dai_type we can remove any dependencies on copiers. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://msgid.link/r/20240213101247.28887-13-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai-ops.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index f58539d2f937..5a5ef93858be 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -633,12 +633,11 @@ hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidg { struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; struct sof_ipc4_pipeline *pipeline = pipe_widget->private; - struct sof_ipc4_copier *ipc4_copier = sdai->private; const struct sof_intel_dsp_desc *chip; chip = get_chip_info(sdev->pdata); - switch (ipc4_copier->dai_type) { + switch (sdai->type) { case SOF_DAI_INTEL_HDA: if (pipeline->use_chain_dma) return &hda_ipc4_chain_dma_ops; From 0c3d57365a03ec920cc90614527ac11ad5a6f323 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 13 Feb 2024 12:12:45 +0200 Subject: [PATCH 13/15] ASoC: SOF: Intel: hda-dai-ops: add SoundWire dspless mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This mode is only supported starting with LunarLake (ACE_2_0). DMIC and SSP remain supported with the DSP only for now, since they need a DAI configuration that is provided to firmware. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://msgid.link/r/20240213101247.28887-14-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai-ops.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index 5a5ef93858be..c50ca9e72d37 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -607,6 +607,13 @@ static const struct hda_dai_widget_dma_ops hda_dspless_dma_ops = { .get_hlink = hda_get_hlink, }; +static const struct hda_dai_widget_dma_ops sdw_dspless_dma_ops = { + .get_hext_stream = hda_dspless_get_hext_stream, + .setup_hext_stream = hda_dspless_setup_hext_stream, + .calc_stream_format = generic_calc_stream_format, + .get_hlink = sdw_get_hlink, +}; + #endif const struct hda_dai_widget_dma_ops * @@ -614,12 +621,24 @@ hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidg { #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK) struct snd_sof_dai *sdai; + const struct sof_intel_dsp_desc *chip; - if (sdev->dspless_mode_selected) - return &hda_dspless_dma_ops; - + chip = get_chip_info(sdev->pdata); sdai = swidget->private; + if (sdev->dspless_mode_selected) { + switch (sdai->type) { + case SOF_DAI_INTEL_HDA: + return &hda_dspless_dma_ops; + case SOF_DAI_INTEL_ALH: + if (chip->hw_ip_version < SOF_INTEL_ACE_2_0) + return NULL; + return &sdw_dspless_dma_ops; + default: + return NULL; + } + } + switch (sdev->pdata->ipc_type) { case SOF_IPC_TYPE_3: { @@ -633,9 +652,6 @@ hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidg { struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; struct sof_ipc4_pipeline *pipeline = pipe_widget->private; - const struct sof_intel_dsp_desc *chip; - - chip = get_chip_info(sdev->pdata); switch (sdai->type) { case SOF_DAI_INTEL_HDA: From 0afce89ff88a85b09201cd23ec272527faf6a480 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 13 Feb 2024 12:12:46 +0200 Subject: [PATCH 14/15] ASoC: SOF: Intel: lnl: Do not use LNL specific wrappers in DSPless mode When DSPless mode is selected the DMIC/SSP offload status should not be changed since the DSP is not in use. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Link: https://msgid.link/r/20240213101247.28887-15-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/lnl.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c index b2ade2741dce..7ae017a00184 100644 --- a/sound/soc/sof/intel/lnl.c +++ b/sound/soc/sof/intel/lnl.c @@ -98,7 +98,8 @@ int sof_lnl_ops_init(struct snd_sof_dev *sdev) memcpy(&sof_lnl_ops, &sof_hda_common_ops, sizeof(struct snd_sof_dsp_ops)); /* probe */ - sof_lnl_ops.probe = lnl_hda_dsp_probe; + if (!sdev->dspless_mode_selected) + sof_lnl_ops.probe = lnl_hda_dsp_probe; /* shutdown */ sof_lnl_ops.shutdown = hda_dsp_shutdown; @@ -128,8 +129,10 @@ int sof_lnl_ops_init(struct snd_sof_dev *sdev) /* TODO: add core_get and core_put */ /* PM */ - sof_lnl_ops.resume = lnl_hda_dsp_resume; - sof_lnl_ops.runtime_resume = lnl_hda_dsp_runtime_resume; + if (!sdev->dspless_mode_selected) { + sof_lnl_ops.resume = lnl_hda_dsp_resume; + sof_lnl_ops.runtime_resume = lnl_hda_dsp_runtime_resume; + } sof_lnl_ops.get_stream_position = mtl_dsp_get_stream_hda_link_position; From 2065610b5ddd5b58eed1dc3b3c3db27a26ebd4b6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 13 Feb 2024 12:12:47 +0200 Subject: [PATCH 15/15] ASoC: SOF: Intel: hda-dai: add support for dspless mode beyond HDAudio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For SoundWire/ALH, we need to have a dai configured, but we don't want to send a DMA_TLV to firmware. Add additional code branches. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Signed-off-by: Peter Ujfalusi Link: https://msgid.link/r/20240213101247.28887-16-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 4bffd9ea21a9..c1682bcdb5a6 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -83,6 +83,11 @@ hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai sdev = widget_to_sdev(w); + if (!swidget) { + dev_err(sdev->dev, "%s: swidget is NULL\n", __func__); + return NULL; + } + if (sdev->dspless_mode_selected) return hda_select_dai_widget_ops(sdev, swidget); @@ -364,8 +369,11 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream, return ret; } - /* get stream_id */ sdev = widget_to_sdev(w); + if (sdev->dspless_mode_selected) + goto skip_tlv; + + /* get stream_id */ hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); if (!hext_stream) { @@ -398,6 +406,7 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream, dma_config->dma_stream_channel_map.device_count = 0; /* mapping not used */ dma_config->dma_priv_config_size = 0; +skip_tlv: return 0; }