All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
To: alsa-devel@alsa-project.org
Cc: =tiwai@suse.com,
	"Péter Ujfalusi" <peter.ujfalusi@linux.intel.com>,
	"Pierre-Louis Bossart" <pierre-louis.bossart@linux.intel.com>,
	"Ranjani Sridharan" <ranjani.sridharan@linux.intel.com>,
	broonie@kernel.org, "Bard Liao" <yung-chuan.liao@linux.intel.com>
Subject: [PATCH 17/18] ASoC: SOF: topology: Make widget binding IPC agnostic
Date: Mon, 14 Mar 2022 13:05:19 -0700	[thread overview]
Message-ID: <20220314200520.1233427-19-ranjani.sridharan@linux.intel.com> (raw)
In-Reply-To: <20220314200520.1233427-1-ranjani.sridharan@linux.intel.com>

Make widget binding in the topology parser IPC agnostic by introducing a
new op, bind_event, in struct ipc_tplg_widget_ops. Also set the op
for all widget types in the IPC3 topology ops.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 sound/soc/sof/ipc3-topology.c | 192 +++++++++++++++++++++++++++++-
 sound/soc/sof/topology.c      | 217 ++--------------------------------
 2 files changed, 202 insertions(+), 207 deletions(-)

diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c
index 96553d103c85..ea1311192877 100644
--- a/sound/soc/sof/ipc3-topology.c
+++ b/sound/soc/sof/ipc3-topology.c
@@ -8,6 +8,7 @@
 //
 
 #include <uapi/sound/sof/tokens.h>
+#include <sound/pcm_params.h>
 #include "sof-priv.h"
 #include "sof-audio.h"
 #include "ops.h"
@@ -1698,6 +1699,194 @@ static int sof_ipc3_control_free(struct snd_sof_dev *sdev, struct snd_sof_contro
 	return sof_ipc_tx_message(sdev->ipc, fcomp.hdr.cmd, &fcomp, sizeof(fcomp), NULL, 0);
 }
 
+/* send pcm params ipc */
+static int sof_ipc3_keyword_detect_pcm_params(struct snd_sof_widget *swidget, int dir)
+{
+	struct snd_soc_component *scomp = swidget->scomp;
+	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
+	struct sof_ipc_pcm_params_reply ipc_params_reply;
+	struct snd_pcm_hw_params *params;
+	struct sof_ipc_pcm_params pcm;
+	struct snd_sof_pcm *spcm;
+	int ret;
+
+	/* get runtime PCM params using widget's stream name */
+	spcm = snd_sof_find_spcm_name(scomp, swidget->widget->sname);
+	if (!spcm) {
+		dev_err(scomp->dev, "Cannot find PCM for %s\n", swidget->widget->name);
+		return -EINVAL;
+	}
+
+	params = &spcm->params[dir];
+
+	/* set IPC PCM params */
+	memset(&pcm, 0, sizeof(pcm));
+	pcm.hdr.size = sizeof(pcm);
+	pcm.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_PARAMS;
+	pcm.comp_id = swidget->comp_id;
+	pcm.params.hdr.size = sizeof(pcm.params);
+	pcm.params.direction = dir;
+	pcm.params.sample_valid_bytes = params_width(params) >> 3;
+	pcm.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED;
+	pcm.params.rate = params_rate(params);
+	pcm.params.channels = params_channels(params);
+	pcm.params.host_period_bytes = params_period_bytes(params);
+
+	/* set format */
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16:
+		pcm.params.frame_fmt = SOF_IPC_FRAME_S16_LE;
+		break;
+	case SNDRV_PCM_FORMAT_S24:
+		pcm.params.frame_fmt = SOF_IPC_FRAME_S24_4LE;
+		break;
+	case SNDRV_PCM_FORMAT_S32:
+		pcm.params.frame_fmt = SOF_IPC_FRAME_S32_LE;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* send IPC to the DSP */
+	ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm),
+				 &ipc_params_reply, sizeof(ipc_params_reply));
+	if (ret < 0)
+		dev_err(scomp->dev, "%s: PCM params failed for %s\n", __func__,
+			swidget->widget->name);
+
+	return ret;
+}
+
+ /* send stream trigger ipc */
+static int sof_ipc3_keyword_detect_trigger(struct snd_sof_widget *swidget, int cmd)
+{
+	struct snd_soc_component *scomp = swidget->scomp;
+	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
+	struct sof_ipc_stream stream;
+	struct sof_ipc_reply reply;
+	int ret;
+
+	/* set IPC stream params */
+	stream.hdr.size = sizeof(stream);
+	stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | cmd;
+	stream.comp_id = swidget->comp_id;
+
+	/* send IPC to the DSP */
+	ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream,
+				 sizeof(stream), &reply, sizeof(reply));
+	if (ret < 0)
+		dev_err(scomp->dev, "%s: Failed to trigger %s\n", __func__, swidget->widget->name);
+
+	return ret;
+}
+
+static int sof_ipc3_keyword_dapm_event(struct snd_soc_dapm_widget *w,
+				       struct snd_kcontrol *k, int event)
+{
+	struct snd_sof_widget *swidget = w->dobj.private;
+	struct snd_soc_component *scomp;
+	int stream = SNDRV_PCM_STREAM_CAPTURE;
+	struct snd_sof_pcm *spcm;
+	int ret = 0;
+
+	if (!swidget)
+		return 0;
+
+	scomp = swidget->scomp;
+
+	dev_dbg(scomp->dev, "received event %d for widget %s\n",
+		event, w->name);
+
+	/* get runtime PCM params using widget's stream name */
+	spcm = snd_sof_find_spcm_name(scomp, swidget->widget->sname);
+	if (!spcm) {
+		dev_err(scomp->dev, "%s: Cannot find PCM for %s\n", __func__,
+			swidget->widget->name);
+		return -EINVAL;
+	}
+
+	/* process events */
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (spcm->stream[stream].suspend_ignored) {
+			dev_dbg(scomp->dev, "PRE_PMU event ignored, KWD pipeline is already RUNNING\n");
+			return 0;
+		}
+
+		/* set pcm params */
+		ret = sof_ipc3_keyword_detect_pcm_params(swidget, stream);
+		if (ret < 0) {
+			dev_err(scomp->dev, "%s: Failed to set pcm params for widget %s\n",
+				__func__, swidget->widget->name);
+			break;
+		}
+
+		/* start trigger */
+		ret = sof_ipc3_keyword_detect_trigger(swidget, SOF_IPC_STREAM_TRIG_START);
+		if (ret < 0)
+			dev_err(scomp->dev, "%s: Failed to trigger widget %s\n", __func__,
+				swidget->widget->name);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (spcm->stream[stream].suspend_ignored) {
+			dev_dbg(scomp->dev,
+				"POST_PMD event ignored, KWD pipeline will remain RUNNING\n");
+			return 0;
+		}
+
+		/* stop trigger */
+		ret = sof_ipc3_keyword_detect_trigger(swidget, SOF_IPC_STREAM_TRIG_STOP);
+		if (ret < 0)
+			dev_err(scomp->dev, "%s: Failed to trigger widget %s\n", __func__,
+				swidget->widget->name);
+
+		/* pcm free */
+		ret = sof_ipc3_keyword_detect_trigger(swidget, SOF_IPC_STREAM_PCM_FREE);
+		if (ret < 0)
+			dev_err(scomp->dev, "%s: Failed to free PCM for widget %s\n", __func__,
+				swidget->widget->name);
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+/* event handlers for keyword detect component */
+static const struct snd_soc_tplg_widget_events sof_kwd_events[] = {
+	{SOF_KEYWORD_DETECT_DAPM_EVENT, sof_ipc3_keyword_dapm_event},
+};
+
+static int sof_ipc3_widget_bind_event(struct snd_soc_component *scomp,
+				      struct snd_sof_widget *swidget, u16 event_type)
+{
+	struct sof_ipc_comp *ipc_comp;
+
+	/* validate widget event type */
+	switch (event_type) {
+	case SOF_KEYWORD_DETECT_DAPM_EVENT:
+		/* only KEYWORD_DETECT comps should handle this */
+		if (swidget->id != snd_soc_dapm_effect)
+			break;
+
+		ipc_comp = swidget->private;
+		if (ipc_comp && ipc_comp->type != SOF_COMP_KEYWORD_DETECT)
+			break;
+
+		/* bind event to keyword detect comp */
+		return snd_soc_tplg_widget_bind_event(swidget->widget, sof_kwd_events,
+						      ARRAY_SIZE(sof_kwd_events), event_type);
+	default:
+		break;
+	}
+
+	dev_err(scomp->dev, "Invalid event type %d for widget %s\n", event_type,
+		swidget->widget->name);
+
+	return -EINVAL;
+}
+
 /* token list for each topology object */
 static enum sof_tokens host_token_list[] = {
 	SOF_CORE_TOKENS,
@@ -1790,7 +1979,8 @@ static const struct sof_ipc_tplg_widget_ops tplg_ipc3_widget_ops[SND_SOC_DAPM_TY
 				 comp_generic_token_list, ARRAY_SIZE(comp_generic_token_list),
 				 NULL},
 	[snd_soc_dapm_effect] = {sof_widget_update_ipc_comp_process, sof_ipc3_widget_free_comp,
-				 process_token_list, ARRAY_SIZE(process_token_list), NULL},
+				 process_token_list, ARRAY_SIZE(process_token_list),
+				 sof_ipc3_widget_bind_event},
 };
 
 static const struct sof_ipc_tplg_ops ipc3_tplg_ops = {
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index f7adf058a768..70677a36c304 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -14,7 +14,6 @@
 #include <linux/firmware.h>
 #include <linux/workqueue.h>
 #include <sound/tlv.h>
-#include <sound/pcm_params.h>
 #include <uapi/sound/sof/tokens.h>
 #include "sof-priv.h"
 #include "sof-audio.h"
@@ -135,171 +134,6 @@ int sof_update_ipc_object(struct snd_soc_component *scomp, void *object, enum so
 	return 0;
 }
 
-/* send pcm params ipc */
-static int ipc_pcm_params(struct snd_sof_widget *swidget, int dir)
-{
-	struct sof_ipc_pcm_params_reply ipc_params_reply;
-	struct snd_soc_component *scomp = swidget->scomp;
-	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
-	struct sof_ipc_pcm_params pcm;
-	struct snd_pcm_hw_params *params;
-	struct snd_sof_pcm *spcm;
-	int ret;
-
-	memset(&pcm, 0, sizeof(pcm));
-
-	/* get runtime PCM params using widget's stream name */
-	spcm = snd_sof_find_spcm_name(scomp, swidget->widget->sname);
-	if (!spcm) {
-		dev_err(scomp->dev, "error: cannot find PCM for %s\n",
-			swidget->widget->name);
-		return -EINVAL;
-	}
-
-	params = &spcm->params[dir];
-
-	/* set IPC PCM params */
-	pcm.hdr.size = sizeof(pcm);
-	pcm.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_PARAMS;
-	pcm.comp_id = swidget->comp_id;
-	pcm.params.hdr.size = sizeof(pcm.params);
-	pcm.params.direction = dir;
-	pcm.params.sample_valid_bytes = params_width(params) >> 3;
-	pcm.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED;
-	pcm.params.rate = params_rate(params);
-	pcm.params.channels = params_channels(params);
-	pcm.params.host_period_bytes = params_period_bytes(params);
-
-	/* set format */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16:
-		pcm.params.frame_fmt = SOF_IPC_FRAME_S16_LE;
-		break;
-	case SNDRV_PCM_FORMAT_S24:
-		pcm.params.frame_fmt = SOF_IPC_FRAME_S24_4LE;
-		break;
-	case SNDRV_PCM_FORMAT_S32:
-		pcm.params.frame_fmt = SOF_IPC_FRAME_S32_LE;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* send IPC to the DSP */
-	ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm),
-				 &ipc_params_reply, sizeof(ipc_params_reply));
-	if (ret < 0)
-		dev_err(scomp->dev, "error: pcm params failed for %s\n",
-			swidget->widget->name);
-
-	return ret;
-}
-
- /* send stream trigger ipc */
-static int ipc_trigger(struct snd_sof_widget *swidget, int cmd)
-{
-	struct snd_soc_component *scomp = swidget->scomp;
-	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
-	struct sof_ipc_stream stream;
-	struct sof_ipc_reply reply;
-	int ret;
-
-	/* set IPC stream params */
-	stream.hdr.size = sizeof(stream);
-	stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | cmd;
-	stream.comp_id = swidget->comp_id;
-
-	/* send IPC to the DSP */
-	ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream,
-				 sizeof(stream), &reply, sizeof(reply));
-	if (ret < 0)
-		dev_err(scomp->dev, "error: failed to trigger %s\n",
-			swidget->widget->name);
-
-	return ret;
-}
-
-static int sof_keyword_dapm_event(struct snd_soc_dapm_widget *w,
-				  struct snd_kcontrol *k, int event)
-{
-	struct snd_sof_widget *swidget = w->dobj.private;
-	struct snd_soc_component *scomp;
-	int stream = SNDRV_PCM_STREAM_CAPTURE;
-	struct snd_sof_pcm *spcm;
-	int ret = 0;
-
-	if (!swidget)
-		return 0;
-
-	scomp = swidget->scomp;
-
-	dev_dbg(scomp->dev, "received event %d for widget %s\n",
-		event, w->name);
-
-	/* get runtime PCM params using widget's stream name */
-	spcm = snd_sof_find_spcm_name(scomp, swidget->widget->sname);
-	if (!spcm) {
-		dev_err(scomp->dev, "error: cannot find PCM for %s\n",
-			swidget->widget->name);
-		return -EINVAL;
-	}
-
-	/* process events */
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		if (spcm->stream[stream].suspend_ignored) {
-			dev_dbg(scomp->dev, "PRE_PMU event ignored, KWD pipeline is already RUNNING\n");
-			return 0;
-		}
-
-		/* set pcm params */
-		ret = ipc_pcm_params(swidget, stream);
-		if (ret < 0) {
-			dev_err(scomp->dev,
-				"error: failed to set pcm params for widget %s\n",
-				swidget->widget->name);
-			break;
-		}
-
-		/* start trigger */
-		ret = ipc_trigger(swidget, SOF_IPC_STREAM_TRIG_START);
-		if (ret < 0)
-			dev_err(scomp->dev,
-				"error: failed to trigger widget %s\n",
-				swidget->widget->name);
-		break;
-	case SND_SOC_DAPM_POST_PMD:
-		if (spcm->stream[stream].suspend_ignored) {
-			dev_dbg(scomp->dev, "POST_PMD even ignored, KWD pipeline will remain RUNNING\n");
-			return 0;
-		}
-
-		/* stop trigger */
-		ret = ipc_trigger(swidget, SOF_IPC_STREAM_TRIG_STOP);
-		if (ret < 0)
-			dev_err(scomp->dev,
-				"error: failed to trigger widget %s\n",
-				swidget->widget->name);
-
-		/* pcm free */
-		ret = ipc_trigger(swidget, SOF_IPC_STREAM_PCM_FREE);
-		if (ret < 0)
-			dev_err(scomp->dev,
-				"error: failed to trigger widget %s\n",
-				swidget->widget->name);
-		break;
-	default:
-		break;
-	}
-
-	return ret;
-}
-
-/* event handlers for keyword detect component */
-static const struct snd_soc_tplg_widget_events sof_kwd_events[] = {
-	{SOF_KEYWORD_DETECT_DAPM_EVENT, sof_keyword_dapm_event},
-};
-
 static inline int get_tlv_data(const int *p, int tlv[TLV_ITEMS])
 {
 	/* we only support dB scale TLV type at the moment */
@@ -1323,38 +1157,6 @@ static int sof_widget_parse_tokens(struct snd_soc_component *scomp, struct snd_s
 	return ret;
 }
 
-static int sof_widget_bind_event(struct snd_soc_component *scomp,
-				 struct snd_sof_widget *swidget,
-				 u16 event_type)
-{
-	struct sof_ipc_comp *ipc_comp;
-
-	/* validate widget event type */
-	switch (event_type) {
-	case SOF_KEYWORD_DETECT_DAPM_EVENT:
-		/* only KEYWORD_DETECT comps should handle this */
-		if (swidget->id != snd_soc_dapm_effect)
-			break;
-
-		ipc_comp = swidget->private;
-		if (ipc_comp && ipc_comp->type != SOF_COMP_KEYWORD_DETECT)
-			break;
-
-		/* bind event to keyword detect comp */
-		return snd_soc_tplg_widget_bind_event(swidget->widget,
-						      sof_kwd_events,
-						      ARRAY_SIZE(sof_kwd_events),
-						      event_type);
-	default:
-		break;
-	}
-
-	dev_err(scomp->dev,
-		"error: invalid event type %d for widget %s\n",
-		event_type, swidget->widget->name);
-	return -EINVAL;
-}
-
 static int sof_get_token_value(u32 token_id, struct snd_sof_tuple *tuples, int num_tuples)
 {
 	int i;
@@ -1486,14 +1288,17 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index,
 
 	/* bind widget to external event */
 	if (tw->event_type) {
-		ret = sof_widget_bind_event(scomp, swidget,
-					    le16_to_cpu(tw->event_type));
-		if (ret) {
-			dev_err(scomp->dev, "error: widget event binding failed\n");
-			kfree(swidget->private);
-			kfree(swidget->tuples);
-			kfree(swidget);
-			return ret;
+		if (widget_ops[w->id].bind_event) {
+			ret = widget_ops[w->id].bind_event(scomp, swidget,
+							   le16_to_cpu(tw->event_type));
+			if (ret) {
+				dev_err(scomp->dev, "widget event binding failed for %s\n",
+					swidget->widget->name);
+				kfree(swidget->private);
+				kfree(swidget->tuples);
+				kfree(swidget);
+				return ret;
+			}
 		}
 	}
 
-- 
2.25.1


  parent reply	other threads:[~2022-03-14 20:12 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-14 20:05 [PATCH 00/18] Introduce IPC abstraction for SOF topology parsing Ranjani Sridharan
2022-03-14 20:05 ` [PATCH 01/18] ASoC: SOF: Introduce struct snd_sof_dai_link Ranjani Sridharan
2022-03-14 20:05 ` [PATCH] ASoC: SOF: IPC4-tooplogy: Add ccore tokens Ranjani Sridharan
2022-03-14 20:07   ` Ranjani Sridharan
2022-03-14 20:05 ` [PATCH 02/18] ASoC: SOF: IPC: Introduce IPC ops Ranjani Sridharan
2022-03-14 20:05 ` [PATCH 03/18] ASoC: SOF: topology: Add helper function for processing tuple arrays Ranjani Sridharan
2022-03-14 20:05 ` [PATCH 04/18] ASoC: SOF: Introduce IPC3 ops Ranjani Sridharan
2022-03-14 20:05 ` [PATCH 05/18] ASoC: SOF: topology: Make scheduler widget parsing IPC agnostic Ranjani Sridharan
2022-03-14 20:05 ` [PATCH 06/18] ASoC: SOF: topology: Make buffer " Ranjani Sridharan
2022-03-14 20:05 ` [PATCH 07/18] ASoC: SOF: topology: Make pga " Ranjani Sridharan
2022-03-14 20:05 ` [PATCH 08/18] ASoC: SOF: topology: Make mixer " Ranjani Sridharan
2022-03-14 20:05 ` [PATCH 09/18] ASoC: SOF: topology: Make mux/demux " Ranjani Sridharan
2022-03-14 20:05 ` [PATCH 10/18] ASoC: SOF: topology: Make src " Ranjani Sridharan
2022-03-14 20:05 ` [PATCH 11/18] ASoC: SOF: topology: Make asrc " Ranjani Sridharan
2022-03-14 20:05 ` [PATCH 12/18] ASoC: SOF: topology: Make siggen " Ranjani Sridharan
2022-03-14 20:05 ` [PATCH 13/18] ASoC: SOF: topology: Make effect " Ranjani Sridharan
2022-03-14 20:05 ` [PATCH 14/18] ASoC: SOF: topology: Make route setup " Ranjani Sridharan
2022-03-14 20:05 ` [PATCH 15/18] ASoC: SOF: topology: Make DAI widget parsing " Ranjani Sridharan
2022-03-14 20:05 ` [PATCH 16/18] ASoC: SOF: topology: Make control " Ranjani Sridharan
2022-03-14 20:05 ` Ranjani Sridharan [this message]
2022-03-14 20:05 ` [PATCH 18/18] ASoC: SOF: topology: remove snd_sof_complete_pipeline() Ranjani Sridharan
2022-03-16 20:36 ` [PATCH 00/18] Introduce IPC abstraction for SOF topology parsing 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=20220314200520.1233427-19-ranjani.sridharan@linux.intel.com \
    --to=ranjani.sridharan@linux.intel.com \
    --cc==tiwai@suse.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=broonie@kernel.org \
    --cc=peter.ujfalusi@linux.intel.com \
    --cc=pierre-louis.bossart@linux.intel.com \
    --cc=yung-chuan.liao@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.