]> git.alsa-project.org Git - alsa-lib.git/commitdiff
support for period wakeup disabling
authorClemens Ladisch <clemens@ladisch.de>
Mon, 15 Nov 2010 09:43:13 +0000 (10:43 +0100)
committerClemens Ladisch <clemens@ladisch.de>
Mon, 15 Nov 2010 09:43:13 +0000 (10:43 +0100)
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
include/sound/asound.h
src/pcm/pcm.c
src/pcm/pcm_local.h

index f3618c3d1437c1add116a4467c55e1f55c5d5de0..7243ffb33d751e23e240f63b5523b768e3e50991 100644 (file)
@@ -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);
index fa889381851053490c911da5465f2bd0652c3895..17dfe8f795b67e286b0b0a6cd973d9ed966b67b3 100644 (file)
@@ -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;
index a49b5b943c206512236e55b0f8e4bd34ede4875f..f378779ad84da530e396ca14d6155b6b3ba1f304 100644 (file)
@@ -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;
 }
 
@@ -3080,6 +3083,23 @@ int snd_pcm_hw_params_can_sync_start(const snd_pcm_hw_params_t *params)
        return !!(params->info & SNDRV_PCM_INFO_SYNC_START);
 }
 
+/**
+ * \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
@@ -4199,6 +4219,56 @@ int snd_pcm_hw_params_get_export_buffer(snd_pcm_t *pcm, snd_pcm_hw_params_t *par
        return 0;
 }
 
+/**
+ * \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
index 2f6fcd22a9a43d57ffda4f21f95d109b9709c086..2e901d54ee51d3822a0bf15afe8057265627f983 100644 (file)
@@ -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