Alsa-Devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
To: lgirdwood@gmail.com, broonie@kernel.org
Cc: alsa-devel@alsa-project.org,
	pierre-louis.bossart@linux.intel.com,
	ranjani.sridharan@linux.intel.com, kai.vehmanen@linux.intel.com,
	rander.wang@intel.com
Subject: [PATCH 03/12] ASoC: SOF: Add support for DSPless mode
Date: Tue,  4 Apr 2023 12:21:06 +0300	[thread overview]
Message-ID: <20230404092115.27949-4-peter.ujfalusi@linux.intel.com> (raw)
In-Reply-To: <20230404092115.27949-1-peter.ujfalusi@linux.intel.com>

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 <peter.ujfalusi@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Rander Wang <rander.wang@intel.com>
---
 sound/soc/sof/core.c       |  22 +++++--
 sound/soc/sof/debug.c      |   1 +
 sound/soc/sof/pcm.c        |  13 +++-
 sound/soc/sof/pm.c         |   5 ++
 sound/soc/sof/sof-audio.c  |   2 +-
 sound/soc/sof/sof-client.c |   3 +
 sound/soc/sof/topology.c   | 130 ++++++++++++++++++++++++++++++++++++-
 7 files changed, 168 insertions(+), 8 deletions(-)

diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c
index 06bcae631612..9a9d82220fd0 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 ade0507328af..b42b5982cbbc 100644
--- a/sound/soc/sof/debug.c
+++ b/sound/soc/sof/debug.c
@@ -370,6 +370,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 d9b4633bba7a..127b68caf9e1 100644
--- a/sound/soc/sof/pcm.c
+++ b/sound/soc/sof/pcm.c
@@ -330,6 +330,11 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
 			spcm->stream[substream->stream].suspend_ignored = true;
 			return 0;
 		}
+
+		/* On suspend the DMA must be stopped in DSPless mode */
+		if (sdev->dspless_mode_selected)
+			reset_hw_params = true;
+
 		fallthrough;
 	case SNDRV_PCM_TRIGGER_STOP:
 		ipc_first = true;
@@ -705,7 +710,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";
@@ -714,4 +718,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 8d3383085d12..c74ce8d414e7 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-audio.c b/sound/soc/sof/sof-audio.c
index 4f12e137ff63..7651644fcd62 100644
--- a/sound/soc/sof/sof-audio.c
+++ b/sound/soc/sof/sof-audio.c
@@ -688,7 +688,7 @@ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm,
 		struct snd_sof_widget *pipe_widget;
 		struct snd_sof_pipeline *spipe;
 
-		if (!swidget)
+		if (!swidget || sdev->dspless_mode_selected)
 			continue;
 
 		spipe = swidget->spipe;
diff --git a/sound/soc/sof/sof-client.c b/sound/soc/sof/sof-client.c
index 9017f0864cdd..d6b7caa0cf03 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 bc8ca1e05b83..d3d536b0a8f5 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -1144,8 +1144,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);
@@ -2270,6 +2274,126 @@ 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_dev *sdev = snd_soc_component_get_drvdata(scomp);
+		struct snd_sof_widget *swidget;
+		struct snd_sof_dai dai;
+		int ret;
+
+		swidget = kzalloc(sizeof(*swidget), GFP_KERNEL);
+		if (!swidget)
+			return -ENOMEM;
+
+		memset(&dai, 0, sizeof(dai));
+
+		ret = sof_connect_dai_widget(scomp, w, tw, &dai);
+		if (ret) {
+			kfree(swidget);
+			return ret;
+		}
+
+		swidget->scomp = scomp;
+		swidget->widget = w;
+		mutex_init(&swidget->setup_mutex);
+		w->dobj.private = swidget;
+		list_add(&swidget->list, &sdev->widget_list);
+	}
+
+	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)) {
+		struct snd_sof_widget *swidget = dobj->private;
+
+		sof_disconnect_dai_widget(scomp, w);
+
+		if (!swidget)
+			return 0;
+
+		/* remove and free swidget object */
+		list_del(&swidget->list);
+		kfree(swidget);
+	}
+
+	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);
@@ -2287,7 +2411,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);
-- 
2.40.0


  parent reply	other threads:[~2023-04-04  9:22 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-04  9:21 [PATCH 00/12] ASoC: SOF: core/Intel: Introduce DSPless mode Peter Ujfalusi
2023-04-04  9:21 ` [PATCH 01/12] ASoC: SOF: Intel: hda-stream: Do not dereference hstream until it is safe Peter Ujfalusi
2023-04-04  9:21 ` [PATCH 02/12] ASoC: SOF: Add flag and state which will be used for DSP-less mode Peter Ujfalusi
2023-04-04  9:21 ` Peter Ujfalusi [this message]
2023-04-04  9:21 ` [PATCH 04/12] ASoC: SOF: Intel: hda: Skip interfaces not supported on a platform Peter Ujfalusi
2023-04-04  9:21 ` [PATCH 05/12] ASoC: SOF: Intel: hda: Add support for DSPless mode Peter Ujfalusi
2023-04-04  9:21 ` [PATCH 06/12] ASoC: SOF: Intel: hda: make DSPless mode work with DSP disabled in BIOS Peter Ujfalusi
2023-04-04  9:21 ` [PATCH 07/12] ASoC: SOF: Intel: pci-apl: Allow DSPless mode Peter Ujfalusi
2023-04-04  9:21 ` [PATCH 08/12] ASoC: SOF: Intel: pci-cnl: " Peter Ujfalusi
2023-04-04  9:21 ` [PATCH 09/12] ASoC: SOF: Intel: pci-icl: " Peter Ujfalusi
2023-04-04  9:21 ` [PATCH 10/12] ASoC: SOF: Intel: pci-mtl: " Peter Ujfalusi
2023-04-04  9:21 ` [PATCH 11/12] ASoC: SOF: Intel: pci-skl: " Peter Ujfalusi
2023-04-04  9:21 ` [PATCH 12/12] ASoC: SOF: Intel: pci-tgl: " Peter Ujfalusi
2023-04-04 18:05 ` [PATCH 00/12] ASoC: SOF: core/Intel: Introduce " Mark Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230404092115.27949-4-peter.ujfalusi@linux.intel.com \
    --to=peter.ujfalusi@linux.intel.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=broonie@kernel.org \
    --cc=kai.vehmanen@linux.intel.com \
    --cc=lgirdwood@gmail.com \
    --cc=pierre-louis.bossart@linux.intel.com \
    --cc=rander.wang@intel.com \
    --cc=ranjani.sridharan@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox