diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index b5fc0cd93..eb00281e5 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -1049,6 +1049,12 @@ static void suspend(struct userdata *u) { pa_sink_set_max_rewind_within_thread(u->sink, 0); pa_sink_set_max_request_within_thread(u->sink, 0); + /* Disabling the UCM devices may save some power. */ + if (u->ucm_context) { + pa_alsa_ucm_port_data *data = PA_DEVICE_PORT_DATA(u->sink->active_port); + pa_alsa_ucm_port_enable_devices(data, false); + } + pa_log_info("Device suspended..."); } @@ -1164,6 +1170,13 @@ static int unsuspend(struct userdata *u, bool recovering) { pa_log_info("Trying resume..."); + /* We disable all UCM devices when suspending, so let's enable them + * again. */ + if (u->ucm_context) { + pa_alsa_ucm_port_data *data = PA_DEVICE_PORT_DATA(u->sink->active_port); + pa_alsa_ucm_port_enable_devices(data, true); + } + if ((is_iec958(u) || is_hdmi(u)) && pa_sink_is_passthrough(u->sink)) { /* Need to open device in NONAUDIO mode */ int len = strlen(u->device_name) + 8; diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c index 829216a8a..2044b30d0 100644 --- a/src/modules/alsa/alsa-source.c +++ b/src/modules/alsa/alsa-source.c @@ -954,6 +954,12 @@ static void suspend(struct userdata *u) { /* Close PCM device */ close_pcm(u); + /* Disabling the UCM devices may save some power. */ + if (u->ucm_context) { + pa_alsa_ucm_port_data *data = PA_DEVICE_PORT_DATA(u->source->active_port); + pa_alsa_ucm_port_enable_devices(data, false); + } + pa_log_info("Device suspended..."); } @@ -1044,6 +1050,13 @@ static int unsuspend(struct userdata *u, bool recovering) { pa_log_info("Trying resume..."); + /* We disable all UCM devices when suspending, so let's enable them + * again. */ + if (u->ucm_context) { + pa_alsa_ucm_port_data *data = PA_DEVICE_PORT_DATA(u->source->active_port); + pa_alsa_ucm_port_enable_devices(data, true); + } + if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK| SND_PCM_NO_AUTO_RESAMPLE| diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c index 1df8eb227..34d209b06 100644 --- a/src/modules/alsa/alsa-ucm.c +++ b/src/modules/alsa/alsa-ucm.c @@ -2245,6 +2245,29 @@ static void ucm_port_update_available(pa_alsa_ucm_port_data *port) { pa_device_port_set_available(port->core_port, available); } +void pa_alsa_ucm_port_enable_devices(pa_alsa_ucm_port_data *data, bool enable) { + pa_alsa_ucm_device *dev; + uint32_t idx; + + pa_assert(data); + + /* first disable then enable */ + PA_DYNARRAY_FOREACH(dev, data->devices, idx) { + int r; + + if (enable) { + pa_log_debug("Enabling UCM device %s.", dev->name); + if ((r = snd_use_case_set(data->ucm->ucm_mgr, "_enadev", dev->name) < 0)) + pa_log("Failed to enable UCM device %s: %s", dev->name, pa_cstrerror(r)); + } else { + pa_log_debug("Disabling UCM device %s.", dev->name); + if ((r = snd_use_case_set(data->ucm->ucm_mgr, "_disdev", dev->name) < 0)) + pa_log("Failed to disable UCM device %s: %s", dev->name, pa_cstrerror(r)); + } + } +} + + #else /* HAVE_ALSA_UCM */ /* Dummy functions for systems without UCM support */ @@ -2301,4 +2324,7 @@ void pa_alsa_ucm_roled_stream_begin(pa_alsa_ucm_config *ucm, const char *role, p void pa_alsa_ucm_roled_stream_end(pa_alsa_ucm_config *ucm, const char *role, pa_direction_t dir) { } +void pa_alsa_ucm_port_enable_devices(pa_alsa_ucm_port_data *data, bool enable) { +} + #endif diff --git a/src/modules/alsa/alsa-ucm.h b/src/modules/alsa/alsa-ucm.h index 3bc8345b1..a64fc8476 100644 --- a/src/modules/alsa/alsa-ucm.h +++ b/src/modules/alsa/alsa-ucm.h @@ -285,6 +285,8 @@ struct pa_alsa_ucm_port_data { int eld_device; /* PCM device number */ }; +void pa_alsa_ucm_port_enable_devices(pa_alsa_ucm_port_data *data, bool enable); + struct pa_alsa_ucm_volume { char *mixer_elem; /* mixer element identifier */ char *master_elem; /* master mixer element identifier */