From: "Amadeusz Sławiński" <amadeuszx.slawinski@linux.intel.com>
To: Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.com>,
Mark Brown <broonie@kernel.org>
Cc: "Cezary Rojewski" <cezary.rojewski@intel.com>,
linux-sound@vger.kernel.org,
"Amadeusz Sławiński" <amadeuszx.slawinski@linux.intel.com>
Subject: [RFC PATCH 1/4] ALSA: core: Add support for running detect on capture stream
Date: Wed, 16 Oct 2024 15:02:25 +0200 [thread overview]
Message-ID: <20241016130228.1013227-2-amadeuszx.slawinski@linux.intel.com> (raw)
In-Reply-To: <20241016130228.1013227-1-amadeuszx.slawinski@linux.intel.com>
In order to save power when running detection on capture streams, there
is need for additional state which allows stream to be in "half" running
state. Goal is to allow for DSP to perform detection and then tell
userspace that it detected something and to trigger transfer to running
mode where capture will be performed for further analysis.
Signed-off-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
---
include/sound/pcm.h | 2 +
include/uapi/sound/asound.h | 4 +-
sound/core/pcm_native.c | 77 ++++++++++++++++++++++++++++++++++++-
3 files changed, 80 insertions(+), 3 deletions(-)
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 0bf7d25434d7f..f06ef7c718733 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -102,6 +102,8 @@ struct snd_pcm_ops {
#define SNDRV_PCM_TRIGGER_SUSPEND 5
#define SNDRV_PCM_TRIGGER_RESUME 6
#define SNDRV_PCM_TRIGGER_DRAIN 7
+#define SNDRV_PCM_TRIGGER_DETECT_STOP 8
+#define SNDRV_PCM_TRIGGER_DETECT_START 9
#define SNDRV_PCM_POS_XRUN ((snd_pcm_uframes_t)-1)
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
index 4cd513215bcd8..c9f53d79638be 100644
--- a/include/uapi/sound/asound.h
+++ b/include/uapi/sound/asound.h
@@ -313,7 +313,8 @@ typedef int __bitwise snd_pcm_state_t;
#define SNDRV_PCM_STATE_PAUSED ((__force snd_pcm_state_t) 6) /* stream is paused */
#define SNDRV_PCM_STATE_SUSPENDED ((__force snd_pcm_state_t) 7) /* hardware is suspended */
#define SNDRV_PCM_STATE_DISCONNECTED ((__force snd_pcm_state_t) 8) /* hardware is disconnected */
-#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DISCONNECTED
+#define SNDRV_PCM_STATE_DETECTING ((__force snd_pcm_state_t) 9) /* stream is detecting (e.g. voice detection) */
+#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DETECTING
enum {
SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
@@ -703,6 +704,7 @@ enum {
#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct snd_xferi)
#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct snd_xfern)
#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_DETECT _IO('A', 0x54)
#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int)
#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61)
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index b465fb6e1f5f0..4fe1d2f41149c 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1410,6 +1410,72 @@ static int snd_pcm_action_nonatomic(const struct action_ops *ops,
return res;
}
+/*
+ * detection callbacks
+ */
+
+static int snd_pcm_pre_detect(struct snd_pcm_substream *substream,
+ snd_pcm_state_t state)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ if (runtime->status->state != SNDRV_PCM_STATE_PREPARED)
+ return -EBADFD;
+ /* Detection only makes sense on capture stream */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ return -EINVAL;
+ runtime->trigger_tstamp_latched = false;
+ runtime->trigger_master = substream;
+ return 0;
+}
+
+static int snd_pcm_do_detect(struct snd_pcm_substream *substream,
+ snd_pcm_state_t state)
+{
+ if (substream->runtime->trigger_master != substream)
+ return 0;
+ return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_DETECT_START);
+}
+
+static void snd_pcm_undo_detect(struct snd_pcm_substream *substream,
+ snd_pcm_state_t state)
+{
+ if (substream->runtime->trigger_master == substream)
+ substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_DETECT_STOP);
+}
+
+static void snd_pcm_post_detect(struct snd_pcm_substream *substream,
+ snd_pcm_state_t state)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ snd_pcm_trigger_tstamp(substream);
+ runtime->hw_ptr_jiffies = jiffies;
+ runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) / runtime->rate;
+ runtime->status->state = state;
+ snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTART);
+}
+
+static const struct action_ops snd_pcm_action_detect = {
+ .pre_action = snd_pcm_pre_detect,
+ .do_action = snd_pcm_do_detect,
+ .undo_action = snd_pcm_undo_detect,
+ .post_action = snd_pcm_post_detect,
+};
+
+/**
+ * snd_pcm_detect - start all detection streams
+ * @substream: the PCM substream instance
+ *
+ * Return: Zero if successful, or a negative error code.
+ * The stream lock must be acquired before calling this function.
+ */
+int snd_pcm_detect(struct snd_pcm_substream *substream)
+{
+ return snd_pcm_action_lock_irq(&snd_pcm_action_detect, substream,
+ SNDRV_PCM_STATE_DETECTING);
+}
+
/*
* start callbacks
*/
@@ -1417,7 +1483,8 @@ static int snd_pcm_pre_start(struct snd_pcm_substream *substream,
snd_pcm_state_t state)
{
struct snd_pcm_runtime *runtime = substream->runtime;
- if (runtime->state != SNDRV_PCM_STATE_PREPARED)
+ if (runtime->state != SNDRV_PCM_STATE_PREPARED &&
+ runtime->state != SNDRV_PCM_STATE_DETECTING)
return -EBADFD;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
!snd_pcm_playback_data(substream))
@@ -2919,10 +2986,14 @@ static int snd_pcm_release(struct inode *inode, struct file *file)
static int do_pcm_hwsync(struct snd_pcm_substream *substream)
{
switch (substream->runtime->state) {
+ case SNDRV_PCM_STATE_DETECTING:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ return -EBADFD;
+ return snd_pcm_update_hw_ptr(substream);
case SNDRV_PCM_STATE_DRAINING:
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
return -EBADFD;
- fallthrough;
+ return snd_pcm_update_hw_ptr(substream);
case SNDRV_PCM_STATE_RUNNING:
return snd_pcm_update_hw_ptr(substream);
case SNDRV_PCM_STATE_PREPARED:
@@ -3342,6 +3413,8 @@ static int snd_pcm_common_ioctl(struct file *file,
return snd_pcm_prepare(substream, file);
case SNDRV_PCM_IOCTL_RESET:
return snd_pcm_reset(substream);
+ case SNDRV_PCM_IOCTL_DETECT:
+ return snd_pcm_detect(substream);
case SNDRV_PCM_IOCTL_START:
return snd_pcm_start_lock_irq(substream);
case SNDRV_PCM_IOCTL_LINK:
--
2.34.1
next prev parent reply other threads:[~2024-10-16 13:01 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-16 13:02 [RFC PATCH 0/4] Add support for detection Amadeusz Sławiński
2024-10-16 13:02 ` Amadeusz Sławiński [this message]
2024-10-16 13:02 ` [RFC PATCH 2/4] ALSA: core: Allow polling " Amadeusz Sławiński
2024-10-16 13:02 ` [RFC PATCH 3/4] ASoC: pcm: Add support for running detect on capture stream Amadeusz Sławiński
2024-10-16 13:02 ` [RFC PATCH 4/4] ASoC: Propagate DETECT trigger Amadeusz Sławiński
2024-10-16 13:11 ` [RFC PATCH 0/4] Add support for detection Takashi Iwai
2024-10-16 13:29 ` Amadeusz Sławiński
2024-10-16 13:47 ` Takashi Iwai
2024-10-18 14:16 ` Amadeusz Sławiński
2024-10-18 17:15 ` Jaroslav Kysela
2024-10-22 15:11 ` Amadeusz Sławiński
2024-10-16 13:41 ` Jaroslav Kysela
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=20241016130228.1013227-2-amadeuszx.slawinski@linux.intel.com \
--to=amadeuszx.slawinski@linux.intel.com \
--cc=broonie@kernel.org \
--cc=cezary.rojewski@intel.com \
--cc=linux-sound@vger.kernel.org \
--cc=perex@perex.cz \
--cc=tiwai@suse.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