OBS-URL: https://build.opensuse.org/package/show/multimedia:libs/alsa?expand=0&rev=67
176 lines
7.1 KiB
Diff
176 lines
7.1 KiB
Diff
From 7c99bd24bcf6852d55e90e0f42f7ac5ea8f14fbb Mon Sep 17 00:00:00 2001
|
|
From: Clemens Ladisch <clemens@ladisch.de>
|
|
Date: Mon, 15 Nov 2010 10:43:13 +0100
|
|
Subject: [PATCH 06/10] support for period wakeup disabling
|
|
|
|
Add API to disable period wakeups.
|
|
|
|
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
|
|
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
|
|
---
|
|
include/pcm.h | 3 ++
|
|
include/sound/asound.h | 2 +
|
|
src/pcm/pcm.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++-
|
|
src/pcm/pcm_local.h | 3 ++
|
|
4 files changed, 79 insertions(+), 1 deletions(-)
|
|
|
|
diff --git a/include/pcm.h b/include/pcm.h
|
|
index f3618c3..7243ffb 100644
|
|
--- a/include/pcm.h
|
|
+++ b/include/pcm.h
|
|
@@ -531,6 +531,7 @@ int snd_pcm_hw_params_can_resume(const snd_pcm_hw_params_t *params);
|
|
int snd_pcm_hw_params_is_half_duplex(const snd_pcm_hw_params_t *params);
|
|
int snd_pcm_hw_params_is_joint_duplex(const snd_pcm_hw_params_t *params);
|
|
int snd_pcm_hw_params_can_sync_start(const snd_pcm_hw_params_t *params);
|
|
+int snd_pcm_hw_params_can_disable_period_wakeup(const snd_pcm_hw_params_t *params);
|
|
int snd_pcm_hw_params_get_rate_numden(const snd_pcm_hw_params_t *params,
|
|
unsigned int *rate_num,
|
|
unsigned int *rate_den);
|
|
@@ -626,6 +627,8 @@ int snd_pcm_hw_params_set_rate_resample(snd_pcm_t *pcm, snd_pcm_hw_params_t *par
|
|
int snd_pcm_hw_params_get_rate_resample(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val);
|
|
int snd_pcm_hw_params_set_export_buffer(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val);
|
|
int snd_pcm_hw_params_get_export_buffer(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val);
|
|
+int snd_pcm_hw_params_set_period_wakeup(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val);
|
|
+int snd_pcm_hw_params_get_period_wakeup(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val);
|
|
|
|
int snd_pcm_hw_params_get_period_time(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
|
|
int snd_pcm_hw_params_get_period_time_min(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
|
|
diff --git a/include/sound/asound.h b/include/sound/asound.h
|
|
index fa88938..17dfe8f 100644
|
|
--- a/include/sound/asound.h
|
|
+++ b/include/sound/asound.h
|
|
@@ -278,6 +278,7 @@ enum sndrv_pcm_subformat {
|
|
#define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000 /* only half duplex */
|
|
#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */
|
|
#define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */
|
|
+#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000 /* period wakeup can be disabled */
|
|
|
|
enum sndrv_pcm_state {
|
|
SNDRV_PCM_STATE_OPEN = 0, /* stream is open */
|
|
@@ -346,6 +347,7 @@ enum sndrv_pcm_hw_param {
|
|
|
|
#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0) /* avoid rate resampling */
|
|
#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER (1<<1) /* export buffer */
|
|
+#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP (1<<2) /* disable period wakeups */
|
|
|
|
struct sndrv_interval {
|
|
unsigned int min, max;
|
|
diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
|
|
index a49b5b9..f378779 100644
|
|
--- a/src/pcm/pcm.c
|
|
+++ b/src/pcm/pcm.c
|
|
@@ -726,8 +726,11 @@ int snd_pcm_nonblock(snd_pcm_t *pcm, int nonblock)
|
|
return err;
|
|
if (nonblock)
|
|
pcm->mode |= SND_PCM_NONBLOCK;
|
|
- else
|
|
+ else {
|
|
+ if (pcm->hw_flags & SND_PCM_HW_PARAMS_NO_PERIOD_WAKEUP)
|
|
+ return -EINVAL;
|
|
pcm->mode &= ~SND_PCM_NONBLOCK;
|
|
+ }
|
|
return 0;
|
|
}
|
|
|
|
@@ -3081,6 +3084,23 @@ int snd_pcm_hw_params_can_sync_start(const snd_pcm_hw_params_t *params)
|
|
}
|
|
|
|
/**
|
|
+ * \brief Check if hardware can disable period wakeups
|
|
+ * \param params Configuration space
|
|
+ * \return Boolean value
|
|
+ * \retval 0 Hardware cannot disable period wakeups
|
|
+ * \retval 1 Hardware can disable period wakeups
|
|
+ */
|
|
+int snd_pcm_hw_params_can_disable_period_wakeup(const snd_pcm_hw_params_t *params)
|
|
+{
|
|
+ assert(params);
|
|
+ if (CHECK_SANITY(params->info == ~0U)) {
|
|
+ SNDMSG("invalid PCM info field");
|
|
+ return 0; /* FIXME: should be a negative error? */
|
|
+ }
|
|
+ return !!(params->info & SNDRV_PCM_INFO_NO_PERIOD_WAKEUP);
|
|
+}
|
|
+
|
|
+/**
|
|
* \brief Get rate exact info from a configuration space
|
|
* \param params Configuration space
|
|
* \param rate_num Pointer to returned rate numerator
|
|
@@ -4200,6 +4220,56 @@ int snd_pcm_hw_params_get_export_buffer(snd_pcm_t *pcm, snd_pcm_hw_params_t *par
|
|
}
|
|
|
|
/**
|
|
+ * \brief Restrict a configuration space to settings without period wakeups
|
|
+ * \param pcm PCM handle
|
|
+ * \param params Configuration space
|
|
+ * \param val 0 = disable, 1 = enable (default) period wakeup
|
|
+ * \return Zero on success, otherwise a negative error code.
|
|
+ *
|
|
+ * This function must be called only on devices where non-blocking mode is
|
|
+ * enabled.
|
|
+ *
|
|
+ * To check whether the hardware does support disabling period wakeups, call
|
|
+ * #snd_pcm_hw_params_can_disable_period_wakeup(). If the hardware does not
|
|
+ * support this mode, standard period wakeups will be generated.
|
|
+ *
|
|
+ * Even with disabled period wakeups, the period size/time/count parameters
|
|
+ * are valid; it is suggested to use #snd_pcm_hw_params_set_period_size_last().
|
|
+ *
|
|
+ * When period wakeups are disabled, the application must not use any functions
|
|
+ * that could block on this device. The use of poll should be limited to error
|
|
+ * cases. The application needs to use an external event or a timer to
|
|
+ * check the state of the ring buffer and refill it apropriately.
|
|
+ */
|
|
+int snd_pcm_hw_params_set_period_wakeup(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val)
|
|
+{
|
|
+ assert(pcm && params);
|
|
+
|
|
+ if (!val) {
|
|
+ if (!(pcm->mode & SND_PCM_NONBLOCK))
|
|
+ return -EINVAL;
|
|
+ params->flags |= SND_PCM_HW_PARAMS_NO_PERIOD_WAKEUP;
|
|
+ } else
|
|
+ params->flags &= ~SND_PCM_HW_PARAMS_NO_PERIOD_WAKEUP;
|
|
+
|
|
+ return snd_pcm_hw_refine(pcm, params);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * \brief Extract period wakeup flag from a configuration space
|
|
+ * \param pcm PCM handle
|
|
+ * \param params Configuration space
|
|
+ * \param val 0 = disabled, 1 = enabled period wakeups
|
|
+ * \return Zero on success, otherwise a negative error code.
|
|
+ */
|
|
+int snd_pcm_hw_params_get_period_wakeup(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val)
|
|
+{
|
|
+ assert(pcm && params && val);
|
|
+ *val = params->flags & SND_PCM_HW_PARAMS_NO_PERIOD_WAKEUP ? 0 : 1;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
* \brief Extract period time from a configuration space
|
|
* \param params Configuration space
|
|
* \param val Returned approximate period duration in us
|
|
diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h
|
|
index 2f6fcd2..2e901d5 100644
|
|
--- a/src/pcm/pcm_local.h
|
|
+++ b/src/pcm/pcm_local.h
|
|
@@ -91,9 +91,12 @@ typedef enum sndrv_pcm_hw_param snd_pcm_hw_param_t;
|
|
#define SND_PCM_INFO_JOINT_DUPLEX SNDRV_PCM_INFO_JOINT_DUPLEX
|
|
/** device can do a kind of synchronized start */
|
|
#define SND_PCM_INFO_SYNC_START SNDRV_PCM_INFO_SYNC_START
|
|
+/** device can disable period wakeups */
|
|
+#define SND_PCM_INFO_NO_PERIOD_WAKEUP SNDRV_PCM_INFO_NO_PERIOD_WAKEUP
|
|
|
|
#define SND_PCM_HW_PARAMS_NORESAMPLE SNDRV_PCM_HW_PARAMS_NORESAMPLE
|
|
#define SND_PCM_HW_PARAMS_EXPORT_BUFFER SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER
|
|
+#define SND_PCM_HW_PARAMS_NO_PERIOD_WAKEUP SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP
|
|
|
|
#define SND_PCM_INFO_MONOTONIC 0x80000000
|
|
|
|
--
|
|
1.7.3.1
|
|
|