From 90c088bdf7e237b7213352d8d61444ceeb220021 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 21 Nov 2022 15:08:10 +0200 Subject: [PATCH 01/12] ASoC: SOF: Intel: hda-stream: Do not dereference hstream until it is safe Only access hext_stream->hstream after it has been checked for NULL pointer Signed-off-by: Peter Ujfalusi --- sound/soc/sof/intel/hda-stream.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index c37ef581637f40..50e92996f92878 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -485,9 +485,8 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, { const struct sof_intel_dsp_desc *chip = get_chip_info(sdev->pdata); struct hdac_bus *bus = sof_to_bus(sdev); - struct hdac_stream *hstream = &hext_stream->hstream; - int sd_offset = SOF_STREAM_SD_OFFSET(hstream); - int ret; + struct hdac_stream *hstream; + int sd_offset, ret; u32 dma_start = SOF_HDA_SD_CTL_DMA_START; u32 mask; u32 run; @@ -502,6 +501,9 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, return -ENODEV; } + hstream = &hext_stream->hstream; + sd_offset = SOF_STREAM_SD_OFFSET(hstream); + /* decouple host and link DMA */ mask = 0x1 << hstream->index; snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, From 3a81ea51c5b174dae7c387a7554183e81d98636b Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Sun, 9 Oct 2022 10:08:02 -0700 Subject: [PATCH 02/12] ASoC: SOF: sof-audio: skip prepare/unprepare if swidget is NULL Skip preparing/unpreparing widgets if the swidget pointer is NULL. This will be true in the case of virtual widgets in topology that were added for reusing the legacy HDA machine driver with SOF. Signed-off-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi --- sound/soc/sof/sof-audio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index ad8cbebf148796..bb2159f09fbc30 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -310,7 +310,7 @@ sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widg struct snd_soc_dapm_path *p; /* skip if the widget is in use or if it is already unprepared */ - if (!swidget->prepared || swidget->use_count > 0) + if (!swidget || !swidget->prepared || swidget->use_count > 0) goto sink_unprepare; widget_ops = tplg_ops ? tplg_ops->widget : NULL; @@ -350,7 +350,7 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget if (!widget_ops) goto sink_prepare; - if (!widget_ops[widget->id].ipc_prepare || swidget->prepared) + if (!swidget || !widget_ops[widget->id].ipc_prepare || swidget->prepared) goto sink_prepare; /* prepare the source widget */ From e25ffe02cd6f9b9541d8d2abf2dc9d8c5f44047c Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 11 Oct 2022 16:18:26 +0300 Subject: [PATCH 03/12] ASoC: SOF: Add flag and state which will be used for DSP-less mode The DSPless mode of the ASoC/SOF driver can be used for hardware verification and debug on platforms with HDaudio codecs. The DSP mode is still needed on existing platforms for SSP, DMIC, SoundWire interfaces managed by the GP-DMA. This mode is also helpful to compare the legacy HDaudio driver with the ASoC/SOF driver wrt. codec management and handling. In theory we use the same code but differences are sometimes seen on jack detection and event handling. Signed-off-by: Peter Ujfalusi --- include/sound/sof.h | 5 +++++ sound/soc/sof/core.c | 9 +++++++++ sound/soc/sof/sof-priv.h | 11 +++++++++++ 3 files changed, 25 insertions(+) diff --git a/include/sound/sof.h b/include/sound/sof.h index 266e66318f9cfd..d3c41f87ac3191 100644 --- a/include/sound/sof.h +++ b/include/sound/sof.h @@ -21,6 +21,7 @@ struct snd_sof_dev; /** * enum sof_fw_state - DSP firmware state definitions * @SOF_FW_BOOT_NOT_STARTED: firmware boot is not yet started + * @SOF_DSPLESS_MODE: DSP is not used * @SOF_FW_BOOT_PREPARE: preparing for boot (firmware loading for exaqmple) * @SOF_FW_BOOT_IN_PROGRESS: firmware boot is in progress * @SOF_FW_BOOT_FAILED: firmware boot failed @@ -31,6 +32,7 @@ struct snd_sof_dev; */ enum sof_fw_state { SOF_FW_BOOT_NOT_STARTED = 0, + SOF_DSPLESS_MODE, SOF_FW_BOOT_PREPARE, SOF_FW_BOOT_IN_PROGRESS, SOF_FW_BOOT_FAILED, @@ -130,6 +132,9 @@ struct sof_dev_desc { unsigned int ipc_supported_mask; enum sof_ipc_type ipc_default; + /* The platform supports DSPless mode */ + bool dspless_mode_supported; + /* defaults paths for firmware, library and topology files */ const char *default_fw_path[SOF_IPC_TYPE_COUNT]; const char *default_lib_path[SOF_IPC_TYPE_COUNT]; diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index a11e622c9f4e8d..5bdbff140f9da0 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -365,6 +365,15 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) if (sof_core_debug) dev_info(dev, "sof_debug value: %#x\n", sof_core_debug); + if (sof_debug_check_flag(SOF_DBG_DSPLESS_MODE)) { + if (plat_data->desc->dspless_mode_supported) { + dev_info(dev, "Switching to DSPless mode\n"); + sdev->dspless_mode_selected = true; + } else { + dev_info(dev, "DSPless mode is not supported by the platform\n"); + } + } + /* check IPC support */ if (!(BIT(plat_data->ipc_type) & plat_data->desc->ipc_supported_mask)) { dev_err(dev, "ipc_type %d is not supported on this platform, mask is %#x\n", diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 5b42a32f874fc6..df7fe0960a614e 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -46,6 +46,7 @@ #define SOF_DBG_FORCE_NOCODEC BIT(10) /* ignore all codec-related * configurations */ +#define SOF_DBG_DSPLESS_MODE BIT(15) /* Do not initialize and use the DSP */ /* Flag definitions used for controlling the DSP dump behavior */ #define SOF_DBG_DUMP_REGS BIT(0) @@ -525,6 +526,16 @@ struct snd_sof_dev { spinlock_t ipc_lock; /* lock for IPC users */ spinlock_t hw_lock; /* lock for HW IO access */ + /* + * When true the DSP is not used. + * It is set under the following condition: + * User sets the SOF_DBG_DSPLESS_MODE flag in sof_debug module parameter + * and + * the platform advertises that it can support such mode + * pdata->desc->dspless_mode_supported is true. + */ + bool dspless_mode_selected; + /* Main, Base firmware image */ struct sof_firmware basefw; From 55412f53b96225899c7fce55a108b00e30b70697 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 14 Jul 2022 15:26:54 +0300 Subject: [PATCH 04/12] ASoC: SOF: Add support for DSPless mode Via the SOF_DBG_DSPLESS_MODE sof_debug flag the SOF stack can be asked to not use the DSP for audio. The core's support for DSPless mode is only going to be enabled if the platform reports that it can be used without DSP. Signed-off-by: Peter Ujfalusi --- sound/soc/sof/core.c | 22 ++++++-- sound/soc/sof/debug.c | 1 + sound/soc/sof/pcm.c | 8 ++- sound/soc/sof/pm.c | 5 ++ sound/soc/sof/sof-client.c | 3 ++ sound/soc/sof/topology.c | 103 ++++++++++++++++++++++++++++++++++++- 6 files changed, 135 insertions(+), 7 deletions(-) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 5bdbff140f9da0..c842e0769e0451 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -208,6 +208,11 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) /* set up platform component driver */ snd_sof_new_platform_drv(sdev); + if (sdev->dspless_mode_selected) { + sof_set_fw_state(sdev, SOF_DSPLESS_MODE); + goto skip_dsp_init; + } + /* register any debug/trace capabilities */ ret = snd_sof_dbg_init(sdev); if (ret < 0) { @@ -266,6 +271,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) dev_dbg(sdev->dev, "SOF firmware trace disabled\n"); } +skip_dsp_init: /* hereafter all FW boot flows are for PM reasons */ sdev->first_boot = false; @@ -387,12 +393,18 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) return ret; /* check all mandatory ops */ - if (!sof_ops(sdev) || !sof_ops(sdev)->probe || !sof_ops(sdev)->run || - !sof_ops(sdev)->block_read || !sof_ops(sdev)->block_write || - !sof_ops(sdev)->send_msg || !sof_ops(sdev)->load_firmware || - !sof_ops(sdev)->ipc_msg_data) { + if (!sof_ops(sdev) || !sof_ops(sdev)->probe) { + sof_ops_free(sdev); + dev_err(dev, "missing mandatory ops\n"); + return -EINVAL; + } + + if (!sdev->dspless_mode_selected && + (!sof_ops(sdev)->run || !sof_ops(sdev)->block_read || + !sof_ops(sdev)->block_write || !sof_ops(sdev)->send_msg || + !sof_ops(sdev)->load_firmware || !sof_ops(sdev)->ipc_msg_data)) { sof_ops_free(sdev); - dev_err(dev, "error: missing mandatory ops\n"); + dev_err(dev, "missing mandatory DSP ops\n"); return -EINVAL; } diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index d9a3ce7b69e16c..bbf7202c36facf 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -368,6 +368,7 @@ static const struct soc_fw_state_info { const char *name; } fw_state_dbg[] = { {SOF_FW_BOOT_NOT_STARTED, "SOF_FW_BOOT_NOT_STARTED"}, + {SOF_DSPLESS_MODE, "SOF_DSPLESS_MODE"}, {SOF_FW_BOOT_PREPARE, "SOF_FW_BOOT_PREPARE"}, {SOF_FW_BOOT_IN_PROGRESS, "SOF_FW_BOOT_IN_PROGRESS"}, {SOF_FW_BOOT_FAILED, "SOF_FW_BOOT_FAILED"}, diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 445acb5c3a21bb..bcafcb9b0a3cdb 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -690,7 +690,6 @@ void snd_sof_new_platform_drv(struct snd_sof_dev *sdev) pd->pcm_construct = sof_pcm_new; pd->ignore_machine = drv_name; - pd->be_hw_params_fixup = sof_pcm_dai_link_fixup; pd->be_pcm_base = SOF_BE_PCM_BASE; pd->use_dai_pcm_id = true; pd->topology_name_prefix = "sof"; @@ -699,4 +698,11 @@ void snd_sof_new_platform_drv(struct snd_sof_dev *sdev) pd->module_get_upon_open = 1; pd->legacy_dai_naming = 1; + + /* + * The fixup is only needed when the DSP is in use as with the DSPless + * mode we are directly using the audio interface + */ + if (!sdev->dspless_mode_selected) + pd->be_hw_params_fixup = sof_pcm_dai_link_fixup; } diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 8d3383085d12c4..c74ce8d414e71a 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -103,6 +103,11 @@ static int sof_resume(struct device *dev, bool runtime_resume) return ret; } + if (sdev->dspless_mode_selected) { + sof_set_fw_state(sdev, SOF_DSPLESS_MODE); + return 0; + } + /* * Nothing further to be done for platforms that support the low power * D0 substate. Resume trace and return when resuming from diff --git a/sound/soc/sof/sof-client.c b/sound/soc/sof/sof-client.c index 9017f0864cdda3..d6b7caa0cf0317 100644 --- a/sound/soc/sof/sof-client.c +++ b/sound/soc/sof/sof-client.c @@ -130,6 +130,9 @@ int sof_register_clients(struct snd_sof_dev *sdev) { int ret; + if (sdev->dspless_mode_selected) + return 0; + /* Register platform independent client devices */ ret = sof_register_ipc_flood_test(sdev); if (ret) { diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index a58c8bfcbca420..20cf2893b1d671 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1172,8 +1172,12 @@ static void sof_disconnect_dai_widget(struct snd_soc_component *scomp, static int spcm_bind(struct snd_soc_component *scomp, struct snd_sof_pcm *spcm, int dir) { + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_sof_widget *host_widget; + if (sdev->dspless_mode_selected) + return 0; + host_widget = snd_sof_find_swidget_sname(scomp, spcm->pcm.caps[dir].name, dir); @@ -2290,6 +2294,99 @@ static struct snd_soc_tplg_ops sof_tplg_ops = { .bytes_ext_ops_count = ARRAY_SIZE(sof_bytes_ext_ops), }; +static int snd_sof_dspless_kcontrol(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static const struct snd_soc_tplg_kcontrol_ops sof_dspless_io_ops[] = { + {SOF_TPLG_KCTL_VOL_ID, snd_sof_dspless_kcontrol, snd_sof_dspless_kcontrol}, + {SOF_TPLG_KCTL_BYTES_ID, snd_sof_dspless_kcontrol, snd_sof_dspless_kcontrol}, + {SOF_TPLG_KCTL_ENUM_ID, snd_sof_dspless_kcontrol, snd_sof_dspless_kcontrol}, + {SOF_TPLG_KCTL_SWITCH_ID, snd_sof_dspless_kcontrol, snd_sof_dspless_kcontrol}, +}; + +static int snd_sof_dspless_bytes_ext_get(struct snd_kcontrol *kcontrol, + unsigned int __user *binary_data, + unsigned int size) +{ + return 0; +} + +static int snd_sof_dspless_bytes_ext_put(struct snd_kcontrol *kcontrol, + const unsigned int __user *binary_data, + unsigned int size) +{ + return 0; +} + +static const struct snd_soc_tplg_bytes_ext_ops sof_dspless_bytes_ext_ops[] = { + {SOF_TPLG_KCTL_BYTES_ID, snd_sof_dspless_bytes_ext_get, snd_sof_dspless_bytes_ext_put}, + {SOF_TPLG_KCTL_BYTES_VOLATILE_RO, snd_sof_dspless_bytes_ext_get}, +}; + +/* external widget init - used for any driver specific init */ +static int sof_dspless_widget_ready(struct snd_soc_component *scomp, int index, + struct snd_soc_dapm_widget *w, + struct snd_soc_tplg_dapm_widget *tw) +{ + if (WIDGET_IS_DAI(w->id)) { + struct snd_sof_dai dai; + + memset(&dai, 0, sizeof(dai)); + + return sof_connect_dai_widget(scomp, w, tw, &dai); + } + + return 0; +} + +static int sof_dspless_widget_unload(struct snd_soc_component *scomp, + struct snd_soc_dobj *dobj) +{ + struct snd_soc_dapm_widget *w = container_of(dobj, struct snd_soc_dapm_widget, dobj); + + if (WIDGET_IS_DAI(w->id)) + sof_disconnect_dai_widget(scomp, w); + + return 0; +} + +static int sof_dspless_link_load(struct snd_soc_component *scomp, int index, + struct snd_soc_dai_link *link, + struct snd_soc_tplg_link_config *cfg) +{ + link->platforms->name = dev_name(scomp->dev); + + /* Set nonatomic property for FE dai links for FE-BE compatibility */ + if (!link->no_pcm) + link->nonatomic = true; + + return 0; +} + +static struct snd_soc_tplg_ops sof_dspless_tplg_ops = { + /* external widget init - used for any driver specific init */ + .widget_ready = sof_dspless_widget_ready, + .widget_unload = sof_dspless_widget_unload, + + /* FE DAI - used for any driver specific init */ + .dai_load = sof_dai_load, + .dai_unload = sof_dai_unload, + + /* DAI link - used for any driver specific init */ + .link_load = sof_dspless_link_load, + + /* vendor specific kcontrol handlers available for binding */ + .io_ops = sof_dspless_io_ops, + .io_ops_count = ARRAY_SIZE(sof_dspless_io_ops), + + /* vendor specific bytes ext handlers available for binding */ + .bytes_ext_ops = sof_dspless_bytes_ext_ops, + .bytes_ext_ops_count = ARRAY_SIZE(sof_dspless_bytes_ext_ops), +}; + int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); @@ -2307,7 +2404,11 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file) return ret; } - ret = snd_soc_tplg_component_load(scomp, &sof_tplg_ops, fw); + if (sdev->dspless_mode_selected) + ret = snd_soc_tplg_component_load(scomp, &sof_dspless_tplg_ops, fw); + else + ret = snd_soc_tplg_component_load(scomp, &sof_tplg_ops, fw); + if (ret < 0) { dev_err(scomp->dev, "error: tplg component load failed %d\n", ret); From 199494dfd11c41268143c78bdae117c60c034782 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 8 Nov 2022 09:55:19 +0200 Subject: [PATCH 05/12] ASoC: SOF: Intel: hda: Skip interfaces not supported on a platform Not all interfaces (SSP/DMIC/HDA/SDW) are available on all platforms. If the interface is not even supported then there is no point in executing a probe or query for that interface. Introduce a simple function (hda_get_interface_mask) to query the interfaces supported on the platform. Signed-off-by: Peter Ujfalusi --- sound/soc/sof/intel/hda.c | 50 ++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 65389c7278e2ac..19aad4141a7851 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -44,6 +44,37 @@ #define EXCEPT_MAX_HDR_SIZE 0x400 #define HDA_EXT_ROM_STATUS_SIZE 8 +static u32 hda_get_interface_mask(struct snd_sof_dev *sdev) +{ + const struct sof_intel_dsp_desc *chip; + u32 interface_mask = 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 = BIT(SOF_DAI_INTEL_SSP); + break; + case SOF_INTEL_CAVS_1_5: + case SOF_INTEL_CAVS_1_5_PLUS: + interface_mask = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | + 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 = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | + BIT(SOF_DAI_INTEL_HDA) | BIT(SOF_DAI_INTEL_ALH); + break; + default: + break; + } + + return interface_mask; +} + #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) /* @@ -845,6 +876,7 @@ static int dmic_detect_topology_fixup(struct snd_sof_dev *sdev, static int hda_init_caps(struct snd_sof_dev *sdev) { + u32 interface_mask = hda_get_interface_mask(sdev); struct hdac_bus *bus = sof_to_bus(sdev); struct snd_sof_pdata *pdata = sdev->pdata; struct sof_intel_hda_dev *hdev = pdata->hw_pdata; @@ -865,6 +897,10 @@ static int hda_init_caps(struct snd_sof_dev *sdev) hda_bus_ml_get_capabilities(bus); + /* Skip SoundWire if it is not supported */ + if (!(interface_mask & BIT(SOF_DAI_INTEL_ALH))) + goto skip_soundwire; + /* scan SoundWire capabilities exposed by DSDT */ ret = hda_sdw_acpi_scan(sdev); if (ret < 0) { @@ -1486,12 +1522,16 @@ void hda_set_mach_params(struct snd_soc_acpi_mach *mach, struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev) { + u32 interface_mask = hda_get_interface_mask(sdev); struct snd_sof_pdata *sof_pdata = sdev->pdata; const struct sof_dev_desc *desc = sof_pdata->desc; - struct snd_soc_acpi_mach *mach; + struct snd_soc_acpi_mach *mach = NULL; const char *tplg_filename; - mach = snd_soc_acpi_find_machine(desc->machines); + /* Try I2S or DMIC if it is supported */ + if (interface_mask & (BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC))) + mach = snd_soc_acpi_find_machine(desc->machines); + if (mach) { bool add_extension = false; bool tplg_fixup = false; @@ -1598,10 +1638,8 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev) } } - /* - * If I2S fails, try SoundWire - */ - if (!mach) + /* If I2S fails, try SoundWire if it is supported */ + if (!mach && (interface_mask & BIT(SOF_DAI_INTEL_ALH))) mach = hda_sdw_machine_select(sdev); /* From 9dd5b2347aba8c72bd208f1c3d8ab8271c61e9ce Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 12 Oct 2022 13:54:17 +0300 Subject: [PATCH 06/12] ASoC: SOF: Intel: hda: Add support for DSPless mode Via the SOF_DBG_DSPLESS_MODE sof_debug flag the SOF stack can be asked to not use the DSP for audio. The use of DSPless mode is governed by the sdev->dspless_mode_selected flag which is only going to be set if the user sets sof_debug=0x8000 and the platform advertises that the DSPless mode is supported on them. Signed-off-by: Peter Ujfalusi --- sound/soc/sof/intel/hda-dai-ops.c | 33 +++++++++++++++++++++++++++++- sound/soc/sof/intel/hda-dai.c | 27 ++++++++++++++++++------ sound/soc/sof/intel/hda-pcm.c | 13 +++++++++++- sound/soc/sof/intel/hda-stream.c | 34 ++++++++++++++++--------------- sound/soc/sof/intel/hda.c | 19 ++++++++++------- 5 files changed, 95 insertions(+), 31 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index de48f13259f1d6..4b39cecacd68d0 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -319,13 +319,44 @@ static const struct hda_dai_widget_dma_ops hda_ipc3_dma_ops = { .post_trigger = hda_ipc3_post_trigger, }; +static struct hdac_ext_stream * +hda_dspless_get_hext_stream(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream) +{ + struct hdac_stream *hstream = substream->runtime->private_data; + + return stream_to_hdac_ext_stream(hstream); +} + +static void hda_dspless_setup_hext_stream(struct snd_sof_dev *sdev, + struct hdac_ext_stream *hext_stream, + unsigned int format_val) +{ + /* + * Save the format_val which was adjusted by the maxbps of the codec. + * This information is not available on the FE side since there we are + * using dummy_codec. + */ + hext_stream->hstream.format_val = format_val; +} + +static const struct hda_dai_widget_dma_ops hda_dspless_dma_ops = { + .get_hext_stream = hda_dspless_get_hext_stream, + .setup_hext_stream = hda_dspless_setup_hext_stream, +}; + #endif const struct hda_dai_widget_dma_ops * hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) - struct snd_sof_dai *sdai = swidget->private; + struct snd_sof_dai *sdai; + + if (sdev->dspless_mode_selected) + return &hda_dspless_dma_ops; + + sdai = swidget->private; switch (sdev->pdata->ipc_type) { case SOF_IPC: diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 8afb1baf42e177..727d47072e5323 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -31,12 +31,19 @@ int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, struct snd_sof_dai_config_data *data) { struct snd_sof_widget *swidget = w->dobj.private; - struct snd_soc_component *component = swidget->scomp; - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); + const struct sof_ipc_tplg_ops *tplg_ops; + struct snd_soc_component *component; + struct snd_sof_dev *sdev; int ret; - if (tplg_ops && tplg_ops->dai_config) { + if (!swidget) + return 0; + + component = swidget->scomp; + sdev = snd_soc_component_get_drvdata(component); + tplg_ops = sof_ipc_get_ops(sdev, tplg); + + if (swidget && tplg_ops && tplg_ops->dai_config) { ret = tplg_ops->dai_config(sdev, swidget, flags, data); if (ret < 0) { dev_err(sdev->dev, "DAI config with flags %x failed for widget %s\n", @@ -56,13 +63,21 @@ hda_dai_get_ops(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_sof_dev *sdev = snd_soc_component_get_drvdata(cpu_dai->component); struct snd_sof_widget *swidget = w->dobj.private; - struct snd_sof_dai *sdai = swidget->private; + struct snd_sof_dai *sdai; + + /* + * 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); + + sdai = swidget->private; /* select and set the DAI widget ops if not set already */ if (!sdai->platform_private) { const struct hda_dai_widget_dma_ops *ops = hda_select_dai_widget_ops(sdev, swidget); - if (!ops) return NULL; diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index dc0b359ed9b6cc..9bd7dbdc3f92b2 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -111,7 +111,13 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev, dmab = substream->runtime->dma_buffer_p; - hstream->format_val = rate | bits | (params_channels(params) - 1); + /* + * Use the codec required format val (which is link_bps adjusted) when + * the DSP is not in use + */ + if (!sdev->dspless_mode_selected) + hstream->format_val = rate | bits | (params_channels(params) - 1); + hstream->bufsize = size; hstream->period_bytes = params_period_bytes(params); hstream->no_period_wakeup = @@ -249,6 +255,11 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev, snd_pcm_hw_constraint_integer(substream->runtime, SNDRV_PCM_HW_PARAM_PERIODS); + /* Only S16 and S32 supported by HDA hardware when used without DSP */ + if (sdev->dspless_mode_selected) + snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_FORMAT, + SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_S32); + /* binding pcm substream to hda stream */ substream->runtime->private_data = &dsp_stream->hstream; return 0; diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 50e92996f92878..87e31a65b314c0 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -503,11 +503,12 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, hstream = &hext_stream->hstream; sd_offset = SOF_STREAM_SD_OFFSET(hstream); + mask = BIT(hstream->index); - /* decouple host and link DMA */ - mask = 0x1 << hstream->index; - snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, - mask, mask); + /* decouple host and link DMA if the DSP is used */ + if (!sdev->dspless_mode_selected) + snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, + mask, mask); /* clear stream status */ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, sd_offset, @@ -608,11 +609,10 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, * enable decoupled mode */ - if (chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK) { + if (!sdev->dspless_mode_selected && (chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK)) /* couple host and link DMA, disable DSP features */ snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, mask, 0); - } /* program stream format */ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, @@ -620,11 +620,10 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, SOF_HDA_ADSP_REG_SD_FORMAT, 0xffff, hstream->format_val); - if (chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK) { + if (!sdev->dspless_mode_selected && (chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK)) /* decouple host and link DMA, enable DSP features */ snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, mask, mask); - } /* program last valid index */ snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, @@ -677,20 +676,23 @@ int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream = container_of(hstream, struct hdac_ext_stream, hstream); - struct hdac_bus *bus = sof_to_bus(sdev); - u32 mask = 0x1 << hstream->index; int ret; ret = hda_dsp_stream_reset(sdev, hstream); if (ret < 0) return ret; - spin_lock_irq(&bus->reg_lock); - /* couple host and link DMA if link DMA channel is idle */ - if (!hext_stream->link_locked) - snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, - SOF_HDA_REG_PP_PPCTL, mask, 0); - spin_unlock_irq(&bus->reg_lock); + if (!sdev->dspless_mode_selected) { + struct hdac_bus *bus = sof_to_bus(sdev); + u32 mask = BIT(hstream->index); + + spin_lock_irq(&bus->reg_lock); + /* couple host and link DMA if link DMA channel is idle */ + if (!hext_stream->link_locked) + snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, + SOF_HDA_REG_PP_PPCTL, mask, 0); + spin_unlock_irq(&bus->reg_lock); + } hda_dsp_stream_spib_config(sdev, hext_stream, HDA_DSP_SPIB_DISABLE, 0); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 19aad4141a7851..a14733aa7a60ff 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -47,32 +47,34 @@ static u32 hda_get_interface_mask(struct snd_sof_dev *sdev) { const struct sof_intel_dsp_desc *chip; - u32 interface_mask = 0; + 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 = BIT(SOF_DAI_INTEL_SSP); + interface_mask[0] = BIT(SOF_DAI_INTEL_SSP); break; case SOF_INTEL_CAVS_1_5: case SOF_INTEL_CAVS_1_5_PLUS: - interface_mask = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | - BIT(SOF_DAI_INTEL_HDA); + 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); 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 = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | - BIT(SOF_DAI_INTEL_HDA) | BIT(SOF_DAI_INTEL_ALH); + 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); break; default: break; } - return interface_mask; + return interface_mask[sdev->dspless_mode_selected]; } #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) @@ -1058,6 +1060,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) hdev->no_ipc_position = sof_ops(sdev)->pcm_pointer ? 1 : 0; #endif + if (sdev->dspless_mode_selected) + hdev->no_ipc_position = 1; + /* set up HDA base */ bus = sof_to_bus(sdev); ret = hda_init(sdev); From d3a07ae2ff4c7cfe2a03e59afb34ebc742c55483 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 12 Oct 2022 13:56:03 +0300 Subject: [PATCH 07/12] ASoC: SOF: Intel: pci-apl: Allow DSPless mode set the dspless_mode_supported flag to true for apl family to allow DSPless mode. Signed-off-by: Peter Ujfalusi --- sound/soc/sof/intel/pci-apl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/sof/intel/pci-apl.c b/sound/soc/sof/intel/pci-apl.c index 69279dcc92dc13..a54be4f7bf24ed 100644 --- a/sound/soc/sof/intel/pci-apl.c +++ b/sound/soc/sof/intel/pci-apl.c @@ -29,6 +29,7 @@ static const struct sof_dev_desc bxt_desc = { .chip_info = &apl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/apl", @@ -60,6 +61,7 @@ static const struct sof_dev_desc glk_desc = { .chip_info = &apl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/glk", From 16a20b821aa21aa3f434b6d568ee13ea7b070120 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 1 Dec 2022 11:59:15 +0200 Subject: [PATCH 08/12] ASoC: SOF: Intel: pci-cnl: Allow DSPless mode set the dspless_mode_supported flag to true for cnl/cfl/cml family to allow DSPless mode. Signed-off-by: Peter Ujfalusi --- sound/soc/sof/intel/pci-cnl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/sof/intel/pci-cnl.c b/sound/soc/sof/intel/pci-cnl.c index 8db3f8d15b55e9..d2ae64924b03d9 100644 --- a/sound/soc/sof/intel/pci-cnl.c +++ b/sound/soc/sof/intel/pci-cnl.c @@ -30,6 +30,7 @@ static const struct sof_dev_desc cnl_desc = { .chip_info = &cnl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/cnl", @@ -61,6 +62,7 @@ static const struct sof_dev_desc cfl_desc = { .chip_info = &cnl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/cnl", @@ -93,6 +95,7 @@ static const struct sof_dev_desc cml_desc = { .chip_info = &cnl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/cnl", From b025a8cca590e17f3698dc716aa9d4067cdcbcda Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 1 Dec 2022 11:58:38 +0200 Subject: [PATCH 09/12] ASoC: SOF: Intel: pci-icl: Allow DSPless mode set the dspless_mode_supported flag to true for icl/jsl family to allow DSPless mode. Signed-off-by: Peter Ujfalusi --- sound/soc/sof/intel/pci-icl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/sof/intel/pci-icl.c b/sound/soc/sof/intel/pci-icl.c index d6cf75e357dbf0..35db593dc18186 100644 --- a/sound/soc/sof/intel/pci-icl.c +++ b/sound/soc/sof/intel/pci-icl.c @@ -30,6 +30,7 @@ static const struct sof_dev_desc icl_desc = { .chip_info = &icl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/icl", @@ -61,6 +62,7 @@ static const struct sof_dev_desc jsl_desc = { .chip_info = &jsl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/jsl", From 139199276b80c13e1fac7ddb78b18c06693eedae Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 1 Dec 2022 12:10:50 +0200 Subject: [PATCH 10/12] ASoC: SOF: Intel: pci-mtl: Allow DSPless mode set the dspless_mode_supported flag to true for mtl family to allow DSPless mode. Signed-off-by: Peter Ujfalusi --- sound/soc/sof/intel/pci-mtl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sof/intel/pci-mtl.c b/sound/soc/sof/intel/pci-mtl.c index 6e4e6d4ef5a564..b6dfdf91d04ec8 100644 --- a/sound/soc/sof/intel/pci-mtl.c +++ b/sound/soc/sof/intel/pci-mtl.c @@ -31,6 +31,7 @@ static const struct sof_dev_desc mtl_desc = { .chip_info = &mtl_chip_info, .ipc_supported_mask = BIT(SOF_INTEL_IPC4), .ipc_default = SOF_INTEL_IPC4, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_INTEL_IPC4] = "intel/sof-ipc4/mtl", }, From f35598aac2eb6b9faa6834f8912836f7f0a079c2 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 1 Dec 2022 11:58:19 +0200 Subject: [PATCH 11/12] ASoC: SOF: Intel: pci-skl: Allow DSPless mode set the dspless_mode_supported flag to true for skl family to allow DSPless mode. Signed-off-by: Peter Ujfalusi --- sound/soc/sof/intel/pci-skl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/sof/intel/pci-skl.c b/sound/soc/sof/intel/pci-skl.c index 3a99dc444f92ea..369a0d99e19b0b 100644 --- a/sound/soc/sof/intel/pci-skl.c +++ b/sound/soc/sof/intel/pci-skl.c @@ -26,6 +26,7 @@ static struct sof_dev_desc skl_desc = { .irqindex_host_ipc = -1, .ipc_supported_mask = BIT(SOF_INTEL_IPC4), .ipc_default = SOF_INTEL_IPC4, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_INTEL_IPC4] = "intel/avs/skl", }, @@ -49,6 +50,7 @@ static struct sof_dev_desc kbl_desc = { .irqindex_host_ipc = -1, .ipc_supported_mask = BIT(SOF_INTEL_IPC4), .ipc_default = SOF_INTEL_IPC4, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_INTEL_IPC4] = "intel/avs/kbl", }, From 4936fa6c441783101f04da417f9ea386d3e2d122 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 12 Oct 2022 13:55:49 +0300 Subject: [PATCH 12/12] ASoC: SOF: Intel: pci-tgl: Allow DSPless mode set the dspless_mode_supported flag to true for tgl/adl family to allow DSPless mode. Signed-off-by: Peter Ujfalusi --- sound/soc/sof/intel/pci-tgl.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/sof/intel/pci-tgl.c b/sound/soc/sof/intel/pci-tgl.c index e80c4dfef85a58..52af93e2e9ed3b 100644 --- a/sound/soc/sof/intel/pci-tgl.c +++ b/sound/soc/sof/intel/pci-tgl.c @@ -30,6 +30,7 @@ static const struct sof_dev_desc tgl_desc = { .chip_info = &tgl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/tgl", @@ -61,6 +62,7 @@ static const struct sof_dev_desc tglh_desc = { .chip_info = &tglh_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/tgl-h", @@ -92,6 +94,7 @@ static const struct sof_dev_desc ehl_desc = { .chip_info = &ehl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/ehl", @@ -123,6 +126,7 @@ static const struct sof_dev_desc adls_desc = { .chip_info = &adls_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/adl-s", @@ -154,6 +158,7 @@ static const struct sof_dev_desc adl_desc = { .chip_info = &tgl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/adl", @@ -185,6 +190,7 @@ static const struct sof_dev_desc adl_n_desc = { .chip_info = &tgl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/adl-n", @@ -216,6 +222,7 @@ static const struct sof_dev_desc rpls_desc = { .chip_info = &adls_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/rpl-s", @@ -247,6 +254,7 @@ static const struct sof_dev_desc rpl_desc = { .chip_info = &tgl_chip_info, .ipc_supported_mask = BIT(SOF_IPC) | BIT(SOF_INTEL_IPC4), .ipc_default = SOF_IPC, + .dspless_mode_supported = true, /* Only supported for HDaudio */ .default_fw_path = { [SOF_IPC] = "intel/sof", [SOF_INTEL_IPC4] = "intel/avs/rpl",