OSDN Git Service

Added power management functions and defines.
authorJaroslav Kysela <perex@perex.cz>
Wed, 26 Sep 2001 13:57:04 +0000 (13:57 +0000)
committerJaroslav Kysela <perex@perex.cz>
Wed, 26 Sep 2001 13:57:04 +0000 (13:57 +0000)
19 files changed:
aserver/aserver.c
include/aserver.h
include/control.h
include/pcm.h
src/control/control.c
src/control/control_hw.c
src/control/control_local.h
src/control/control_shm.c
src/pcm/pcm.c
src/pcm/pcm_file.c
src/pcm/pcm_hooks.c
src/pcm/pcm_hw.c
src/pcm/pcm_local.h
src/pcm/pcm_meter.c
src/pcm/pcm_multi.c
src/pcm/pcm_null.c
src/pcm/pcm_plugin.c
src/pcm/pcm_share.c
src/pcm/pcm_shm.c

index 72633a1..6fccb8a 100644 (file)
@@ -469,6 +469,9 @@ static int pcm_shm_cmd(client_t *client)
        case SNDRV_PCM_IOCTL_UNLINK:
                ctrl->result = snd_pcm_unlink(pcm);
                break;
+       case SNDRV_PCM_IOCTL_RESUME:
+               ctrl->result = snd_pcm_resume(pcm);
+               break;
        case SND_PCM_IOCTL_MMAP:
        {
                ctrl->result = snd_pcm_mmap(pcm);
@@ -669,6 +672,12 @@ static int ctl_shm_cmd(client_t *client)
        case SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE:
                ctrl->result = snd_ctl_rawmidi_prefer_subdevice(ctl, ctrl->u.rawmidi_prefer_subdevice);
                break;
+       case SNDRV_CTL_IOCTL_POWER:
+               ctrl->result = snd_ctl_set_power_state(ctl, ctrl->u.power_state);
+               break;
+       case SNDRV_CTL_IOCTL_POWER_STATE:
+               ctrl->result = snd_ctl_get_power_state(ctl, &ctrl->u.power_state);
+               break;
        case SND_CTL_IOCTL_READ:
                ctrl->result = snd_ctl_read(ctl, &ctrl->u.read);
                break;
index 344167a..662e7e9 100644 (file)
@@ -113,6 +113,7 @@ typedef struct {
                int pcm_prefer_subdevice;
                snd_rawmidi_info_t rawmidi_info;
                int rawmidi_prefer_subdevice;
+               unsigned int power_state;
                snd_ctl_event_t read;
        } u;
        char data[0];
index 1c66175..812699d 100644 (file)
@@ -142,6 +142,20 @@ typedef enum _snd_ctl_event_type {
 /** Element name for IEC958 (S/PDIF) */
 #define SND_CTL_NAME_IEC958(expl,direction,what)       "IEC958 " expl SND_CTL_NAME_##direction SND_CTL_NAME_IEC958_##what
 
+/** Mask for the major Power State identifier */
+#define SNDRV_CTL_POWER_MASK           0xff00
+/** ACPI/PCI Power State D0 */
+#define SNDRV_CTL_POWER_D0             0x0000
+/** ACPI/PCI Power State D1 */
+#define SNDRV_CTL_POWER_D1                     0x0100
+/** ACPI/PCI Power State D2 */
+#define SNDRV_CTL_POWER_D2             0x0200
+/** ACPI/PCI Power State D3 */
+#define SNDRV_CTL_POWERDOWN_D3          0x0300
+/** ACPI/PCI Power State D3hot */
+#define SNDRV_CTL_POWERDOWN_D3hot       (SNDRV_CTL_POWERDOWN_D3|0x0000)
+/** ACPI/PCI Power State D3cold */
+#define SNDRV_CTL_POWERDOWN_D3cold      (SNDRV_CTL_POWERDOWN_D3|0x0001)
 
 /** CTL type */
 typedef enum _snd_ctl_type {
@@ -208,6 +222,8 @@ int snd_ctl_pcm_prefer_subdevice(snd_ctl_t *ctl, int subdev);
 int snd_ctl_rawmidi_next_device(snd_ctl_t *ctl, int * device);
 int snd_ctl_rawmidi_info(snd_ctl_t *ctl, snd_rawmidi_info_t * info);
 int snd_ctl_rawmidi_prefer_subdevice(snd_ctl_t *ctl, int subdev);
+int snd_ctl_set_power_state(snd_ctl_t *ctl, unsigned int state);
+int snd_ctl_get_power_state(snd_ctl_t *ctl, unsigned int *state);
 
 int snd_ctl_read(snd_ctl_t *ctl, snd_ctl_event_t *event);
 int snd_ctl_wait(snd_ctl_t *ctl, int timeout);
index 437fe47..d96ae2b 100644 (file)
@@ -222,6 +222,8 @@ typedef enum _snd_pcm_state {
        SND_PCM_STATE_DRAINING,
        /** Paused */
        SND_PCM_STATE_PAUSED,
+       /** Hardware is suspended */
+       SND_PCM_STATE_SUSPENDED,
        SND_PCM_STATE_LAST = SND_PCM_STATE_PAUSED,
 } snd_pcm_state_t;
 
@@ -367,6 +369,7 @@ int snd_pcm_drain(snd_pcm_t *pcm);
 int snd_pcm_pause(snd_pcm_t *pcm, int enable);
 snd_pcm_state_t snd_pcm_state(snd_pcm_t *pcm);
 int snd_pcm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
+int snd_pcm_resume(snd_pcm_t *pcm);
 snd_pcm_sframes_t snd_pcm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
 snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);
 snd_pcm_sframes_t snd_pcm_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size);
index c505a7e..d21a7a0 100644 (file)
@@ -363,6 +363,33 @@ int snd_ctl_rawmidi_prefer_subdevice(snd_ctl_t *ctl, int subdev)
        return ctl->ops->rawmidi_prefer_subdevice(ctl, subdev);
 }
 
+/**
+ * \brief Set Power State to given SND_CTL_POWER_* value and do the power management
+ * \param ctl CTL handle
+ * \param state Desired Power State
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_ctl_set_power_state(snd_ctl_t *ctl, unsigned int state)
+{
+       assert(ctl);
+       if (ctl->ops->set_power_state)
+               return ctl->ops->set_power_state(ctl, state);
+       return -ENXIO;
+}
+
+/**
+ * \brief Get actual Power State
+ * \param ctl CTL handle
+ * \param state Destination value
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_ctl_get_power_state(snd_ctl_t *ctl, unsigned int *state)
+{
+       assert(ctl);
+       if (ctl->ops->get_power_state)
+               return ctl->ops->get_power_state(ctl, state);
+       return -ENXIO;
+}
 
 /**
  * \brief Read an event
index e880142..c206dd2 100644 (file)
@@ -233,6 +233,22 @@ static int snd_ctl_hw_rawmidi_prefer_subdevice(snd_ctl_t *handle, int subdev)
        return 0;
 }
 
+static int snd_ctl_hw_set_power_state(snd_ctl_t *handle, unsigned int state)
+{
+       snd_ctl_hw_t *hw = handle->private_data;
+       if (ioctl(hw->fd, SNDRV_CTL_IOCTL_POWER, &state) < 0)
+               return -errno;
+       return 0;
+}
+
+static int snd_ctl_hw_get_power_state(snd_ctl_t *handle, unsigned int *state)
+{
+       snd_ctl_hw_t *hw = handle->private_data;
+       if (ioctl(hw->fd, SNDRV_CTL_IOCTL_POWER_STATE, state) < 0)
+               return -errno;
+       return 0;
+}
+
 static int snd_ctl_hw_read(snd_ctl_t *handle, snd_ctl_event_t *event)
 {
        snd_ctl_hw_t *hw = handle->private_data;
@@ -263,6 +279,8 @@ snd_ctl_ops_t snd_ctl_hw_ops = {
        rawmidi_next_device: snd_ctl_hw_rawmidi_next_device,
        rawmidi_info: snd_ctl_hw_rawmidi_info,
        rawmidi_prefer_subdevice: snd_ctl_hw_rawmidi_prefer_subdevice,
+       set_power_state: snd_ctl_hw_set_power_state,
+       get_power_state: snd_ctl_hw_get_power_state,
        read: snd_ctl_hw_read,
 };
 
index b3522cf..75c0688 100644 (file)
@@ -41,6 +41,8 @@ typedef struct _snd_ctl_ops {
        int (*rawmidi_next_device)(snd_ctl_t *handle, int *device);
        int (*rawmidi_info)(snd_ctl_t *handle, snd_rawmidi_info_t * info);
        int (*rawmidi_prefer_subdevice)(snd_ctl_t *handle, int subdev);
+       int (*set_power_state)(snd_ctl_t *handle, unsigned int state);
+       int (*get_power_state)(snd_ctl_t *handle, unsigned int *state);
        int (*read)(snd_ctl_t *handle, snd_ctl_event_t *event);
 } snd_ctl_ops_t;
 
index 4e7329e..f4572eb 100644 (file)
@@ -345,6 +345,32 @@ static int snd_ctl_shm_rawmidi_prefer_subdevice(snd_ctl_t *ctl, int subdev)
        return err;
 }
 
+static int snd_ctl_shm_set_power_state(snd_ctl_t *ctl, unsigned int state)
+{
+       snd_ctl_shm_t *shm = ctl->private_data;
+       volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
+       int err;
+       ctrl->u.power_state = state;
+       ctrl->cmd = SNDRV_CTL_IOCTL_POWER;
+       err = snd_ctl_shm_action(ctl);
+       if (err < 0)
+               return err;
+       return err;
+}
+
+static int snd_ctl_shm_get_power_state(snd_ctl_t *ctl, unsigned int *state)
+{
+       snd_ctl_shm_t *shm = ctl->private_data;
+       volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
+       int err;
+       ctrl->cmd = SNDRV_CTL_IOCTL_POWER_STATE;
+       err = snd_ctl_shm_action(ctl);
+       if (err < 0)
+               return err;
+       *state = ctrl->u.power_state;
+       return err;
+}
+
 static int snd_ctl_shm_read(snd_ctl_t *ctl, snd_ctl_event_t *event)
 {
        snd_ctl_shm_t *shm;
@@ -384,6 +410,8 @@ snd_ctl_ops_t snd_ctl_shm_ops = {
        rawmidi_next_device: snd_ctl_shm_rawmidi_next_device,
        rawmidi_info: snd_ctl_shm_rawmidi_info,
        rawmidi_prefer_subdevice: snd_ctl_shm_rawmidi_prefer_subdevice,
+       set_power_state: snd_ctl_shm_set_power_state,
+       get_power_state: snd_ctl_shm_get_power_state,
        read: snd_ctl_shm_read,
 };
 
index 1c79b76..da5e67c 100644 (file)
@@ -281,6 +281,18 @@ int snd_pcm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 }
 
 /**
+ * \brief Resume from suspend, no samples are lost
+ * \param pcm PCM handle
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_pcm_resume(snd_pcm_t *pcm)
+{
+       assert(pcm);
+       assert(pcm->setup);
+       return pcm->fast_ops->resume(pcm->fast_op_arg);
+}
+
+/**
  * \brief Prepare PCM for use
  * \param pcm PCM handle
  * \return 0 on success otherwise a negative error code
index cbd0fdb..9e21d52 100644 (file)
@@ -220,6 +220,12 @@ static snd_pcm_sframes_t snd_pcm_file_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
        return err;
 }
 
+static int snd_pcm_file_resume(snd_pcm_t *pcm)
+{
+       snd_pcm_file_t *file = pcm->private_data;
+       return snd_pcm_resume(file->slave);
+}
+
 static snd_pcm_sframes_t snd_pcm_file_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
 {
        snd_pcm_file_t *file = pcm->private_data;
@@ -388,6 +394,7 @@ snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
        drain: snd_pcm_file_drain,
        pause: snd_pcm_file_pause,
        rewind: snd_pcm_file_rewind,
+       resume: snd_pcm_file_resume,
        writei: snd_pcm_file_writei,
        writen: snd_pcm_file_writen,
        readi: snd_pcm_file_readi,
index 9887946..47f066f 100644 (file)
@@ -150,6 +150,12 @@ static snd_pcm_sframes_t snd_pcm_hooks_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t
        return snd_pcm_rewind(h->slave, frames);
 }
 
+static int snd_pcm_hooks_resume(snd_pcm_t *pcm)
+{
+       snd_pcm_hooks_t *h = pcm->private_data;
+       return snd_pcm_resume(h->slave);
+}
+
 static snd_pcm_sframes_t snd_pcm_hooks_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
 {
        snd_pcm_hooks_t *h = pcm->private_data;
@@ -280,6 +286,7 @@ snd_pcm_fast_ops_t snd_pcm_hooks_fast_ops = {
        drain: snd_pcm_hooks_drain,
        pause: snd_pcm_hooks_pause,
        rewind: snd_pcm_hooks_rewind,
+       resume: snd_pcm_hooks_resume,
        writei: snd_pcm_hooks_writei,
        writen: snd_pcm_hooks_writen,
        readi: snd_pcm_hooks_readi,
index 3148c64..ebbdedf 100644 (file)
@@ -298,6 +298,18 @@ static snd_pcm_sframes_t snd_pcm_hw_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t fra
        return frames;
 }
 
+static int snd_pcm_hw_resume(snd_pcm_t *pcm)
+{
+       snd_pcm_hw_t *hw = pcm->private_data;
+       int fd = hw->fd;
+       if (ioctl(fd, SNDRV_PCM_IOCTL_RESUME) < 0) {
+               if (errno != ENXIO)
+                       SYSERR("SNDRV_PCM_IOCTL_RESUME failed");
+               return -errno;
+       }
+       return 0;
+}
+
 static snd_pcm_sframes_t snd_pcm_hw_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
 {
        snd_pcm_sframes_t result;
@@ -520,6 +532,7 @@ snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
        drain: snd_pcm_hw_drain,
        pause: snd_pcm_hw_pause,
        rewind: snd_pcm_hw_rewind,
+       resume: snd_pcm_hw_resume,
        writei: snd_pcm_hw_writei,
        writen: snd_pcm_hw_writen,
        readi: snd_pcm_hw_readi,
index 27d6afa..4acd958 100644 (file)
@@ -135,6 +135,7 @@ typedef struct {
        int (*pause)(snd_pcm_t *pcm, int enable);
        snd_pcm_state_t (*state)(snd_pcm_t *pcm);
        int (*delay)(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
+       int (*resume)(snd_pcm_t *pcm);
        snd_pcm_sframes_t (*rewind)(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
        snd_pcm_sframes_t (*writei)(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);
        snd_pcm_sframes_t (*writen)(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
index f0e3e63..5451730 100644 (file)
@@ -395,6 +395,12 @@ static snd_pcm_sframes_t snd_pcm_meter_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t
        return err;
 }
 
+static int snd_pcm_meter_resume(snd_pcm_t *pcm)
+{
+       snd_pcm_meter_t *meter = pcm->private_data;
+       return snd_pcm_resume(meter->slave);
+}
+
 static snd_pcm_sframes_t snd_pcm_meter_mmap_commit(snd_pcm_t *pcm,
                                                   snd_pcm_uframes_t offset,
                                                   snd_pcm_uframes_t size)
@@ -601,6 +607,7 @@ snd_pcm_fast_ops_t snd_pcm_meter_fast_ops = {
        drain: snd_pcm_meter_drain,
        pause: snd_pcm_meter_pause,
        rewind: snd_pcm_meter_rewind,
+       resume: snd_pcm_meter_resume,
        writei: snd_pcm_mmap_writei,
        writen: snd_pcm_mmap_writen,
        readi: snd_pcm_mmap_readi,
index a8a5003..0c2f6d1 100644 (file)
@@ -486,6 +486,21 @@ static snd_pcm_sframes_t snd_pcm_multi_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t
        return frames;
 }
 
+static int snd_pcm_multi_resume(snd_pcm_t *pcm)
+{
+       snd_pcm_multi_t *multi = pcm->private_data;
+       int err = 0;
+       unsigned int i;
+       for (i = 0; i < multi->slaves_count; ++i) {
+               if (multi->slaves[i].linked)
+                       continue;
+               err = snd_pcm_resume(multi->slaves[i].pcm);
+               if (err < 0)
+                       return err;
+       }
+       return err;
+}
+
 static snd_pcm_sframes_t snd_pcm_multi_mmap_commit(snd_pcm_t *pcm,
                                                   snd_pcm_uframes_t offset,
                                                   snd_pcm_uframes_t size)
@@ -571,6 +586,7 @@ snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = {
        readi: snd_pcm_mmap_readi,
        readn: snd_pcm_mmap_readn,
        rewind: snd_pcm_multi_rewind,
+       resume: snd_pcm_multi_resume,
        avail_update: snd_pcm_multi_avail_update,
        mmap_commit: snd_pcm_multi_mmap_commit,
 };
index 6360be3..186766c 100644 (file)
@@ -166,6 +166,11 @@ static snd_pcm_sframes_t snd_pcm_null_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t f
        }
 }
 
+static int snd_pcm_null_resume(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
+{
+       return 0;
+}
+
 static snd_pcm_sframes_t snd_pcm_null_fwd(snd_pcm_t *pcm, snd_pcm_uframes_t size)
 {
        snd_pcm_null_t *null = pcm->private_data;
@@ -305,6 +310,7 @@ snd_pcm_fast_ops_t snd_pcm_null_fast_ops = {
        drain: snd_pcm_null_drain,
        pause: snd_pcm_null_pause,
        rewind: snd_pcm_null_rewind,
+       resume: snd_pcm_null_resume,
        writei: snd_pcm_null_writei,
        writen: snd_pcm_null_writen,
        readi: snd_pcm_null_readi,
index 0db059a..2908ff6 100644 (file)
@@ -191,6 +191,12 @@ snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames
        return n;
 }
 
+int snd_pcm_plugin_resume(snd_pcm_t *pcm)
+{
+       snd_pcm_plugin_t *plugin = pcm->private_data;
+       return snd_pcm_resume(plugin->slave);
+}
+
 static snd_pcm_uframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
                                                    const snd_pcm_channel_area_t *areas,
                                                    snd_pcm_uframes_t offset,
@@ -446,6 +452,7 @@ snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
        drain: snd_pcm_plugin_drain,
        pause: snd_pcm_plugin_pause,
        rewind: snd_pcm_plugin_rewind,
+       resume: snd_pcm_plugin_resume,
        writei: snd_pcm_plugin_writei,
        writen: snd_pcm_plugin_writen,
        readi: snd_pcm_plugin_readi,
index 65fab30..a91375b 100644 (file)
@@ -901,6 +901,11 @@ static int snd_pcm_share_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTRI
        return -ENOSYS;
 }
 
+static int snd_pcm_share_resume(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
+{
+       return -ENXIO;
+}
+
 static int snd_pcm_share_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *info)
 {
        snd_pcm_share_t *share = pcm->private_data;
@@ -1184,6 +1189,7 @@ snd_pcm_fast_ops_t snd_pcm_share_fast_ops = {
        readi: snd_pcm_mmap_readi,
        readn: snd_pcm_mmap_readn,
        rewind: snd_pcm_share_rewind,
+       resume: snd_pcm_share_resume,
        avail_update: snd_pcm_share_avail_update,
        mmap_commit: snd_pcm_share_mmap_commit,
 };
index 0b1770c..bbadb25 100644 (file)
@@ -433,6 +433,14 @@ static snd_pcm_sframes_t snd_pcm_shm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t fr
        return snd_pcm_shm_action(pcm);
 }
 
+static int snd_pcm_shm_resume(snd_pcm_t *pcm)
+{
+       snd_pcm_shm_t *shm = pcm->private_data;
+       volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
+       ctrl->cmd = SNDRV_PCM_IOCTL_RESUME;
+       return snd_pcm_shm_action(pcm);
+}
+
 static snd_pcm_sframes_t snd_pcm_shm_mmap_commit(snd_pcm_t *pcm,
                                                 snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
                                                 snd_pcm_uframes_t size)
@@ -506,6 +514,7 @@ snd_pcm_fast_ops_t snd_pcm_shm_fast_ops = {
        drain: snd_pcm_shm_drain,
        pause: snd_pcm_shm_pause,
        rewind: snd_pcm_shm_rewind,
+       resume: snd_pcm_shm_resume,
        writei: snd_pcm_mmap_writei,
        writen: snd_pcm_mmap_writen,
        readi: snd_pcm_mmap_readi,