mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-02 09:01:46 -05:00
alsa-ucm: Disable UCM devices when suspending
Disabling UCM devices might save some power, according to an earlier discussion [1]. Disable them when suspending sinks/sources, and enable them when unsuspending. However, doing only that much introduces problems. The hardware controls we track for volume and mute state can change as part of disabling the UCM device. Enabling it back does not restore it to its pre-suspend state, so the UCM-triggered changes to disable the device will show up on user interfaces and cause confusion. The volume/mute should not be kept in sync with hardware for inactive UCM devices [2]. Skip the callbacks for reading/changing volume/mute state if the UCM device is disabled. This way, the volume/mute controls for sinks/sources are essentially detached from the hardware controls until the UCM device is re-enabled. Finally, sync volume and mute state for the sinks/sources just after we re-enable the UCM devices, to restore things to the pre-suspend state. Combined with the above, this means we can still change volume/mute state in user interfaces while the sink/source is suspended, and its updated value will be applied to the UCM device when it's actually going to be used. [1] https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/294#note_522388 [2] https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/772#note_1872757 Co-developed-by: Tanu Kaskinen <tanuk@iki.fi> [Alper: Rebase, split enable/disable functions, skip volume/mute callbacks if disabled, sync mixer at unsuspend, edit message] Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
This commit is contained in:
parent
3e2bb8a1ec
commit
bafe545da7
4 changed files with 120 additions and 0 deletions
|
|
@ -195,6 +195,7 @@ enum {
|
|||
|
||||
static void userdata_free(struct userdata *u);
|
||||
static int unsuspend(struct userdata *u, bool recovering);
|
||||
static void sync_mixer(struct userdata *u, pa_device_port *port);
|
||||
|
||||
/* FIXME: Is there a better way to do this than device names? */
|
||||
static bool is_iec958(struct userdata *u) {
|
||||
|
|
@ -1087,6 +1088,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_device_disable(data);
|
||||
}
|
||||
|
||||
pa_log_info("Device suspended...");
|
||||
}
|
||||
|
||||
|
|
@ -1202,6 +1209,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_device_enable(data);
|
||||
sync_mixer(u, u->sink->active_port);
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
@ -1508,6 +1522,12 @@ static void sink_get_volume_cb(pa_sink *s) {
|
|||
pa_assert(u->mixer_path);
|
||||
pa_assert(u->mixer_handle);
|
||||
|
||||
if (u->ucm_context) {
|
||||
pa_alsa_ucm_port_data *data = PA_DEVICE_PORT_DATA(s->active_port);
|
||||
if (pa_alsa_ucm_port_device_status(data) <= 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (pa_alsa_path_get_volume(u->mixer_path, u->mixer_handle, &s->channel_map, &r) < 0)
|
||||
return;
|
||||
|
||||
|
|
@ -1538,6 +1558,12 @@ static void sink_set_volume_cb(pa_sink *s) {
|
|||
pa_assert(u->mixer_path);
|
||||
pa_assert(u->mixer_handle);
|
||||
|
||||
if (u->ucm_context) {
|
||||
pa_alsa_ucm_port_data *data = PA_DEVICE_PORT_DATA(s->active_port);
|
||||
if (pa_alsa_ucm_port_device_status(data) <= 0)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Shift up by the base volume */
|
||||
pa_sw_cvolume_divide_scalar(&r, &s->real_volume, s->base_volume);
|
||||
|
||||
|
|
@ -1601,6 +1627,12 @@ static void sink_write_volume_cb(pa_sink *s) {
|
|||
pa_assert(u->mixer_handle);
|
||||
pa_assert(s->flags & PA_SINK_DEFERRED_VOLUME);
|
||||
|
||||
if (u->ucm_context) {
|
||||
pa_alsa_ucm_port_data *data = PA_DEVICE_PORT_DATA(s->active_port);
|
||||
if (pa_alsa_ucm_port_device_status(data) <= 0)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Shift up by the base volume */
|
||||
pa_sw_cvolume_divide_scalar(&hw_vol, &hw_vol, s->base_volume);
|
||||
|
||||
|
|
@ -1639,6 +1671,14 @@ static int sink_get_mute_cb(pa_sink *s, bool *mute) {
|
|||
pa_assert(u->mixer_path);
|
||||
pa_assert(u->mixer_handle);
|
||||
|
||||
if (u->ucm_context) {
|
||||
pa_alsa_ucm_port_data *data = PA_DEVICE_PORT_DATA(s->active_port);
|
||||
if (pa_alsa_ucm_port_device_status(data) <= 0) {
|
||||
*mute = s->muted;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (pa_alsa_path_get_mute(u->mixer_path, u->mixer_handle, mute) < 0)
|
||||
return -1;
|
||||
|
||||
|
|
@ -1652,6 +1692,12 @@ static void sink_set_mute_cb(pa_sink *s) {
|
|||
pa_assert(u->mixer_path);
|
||||
pa_assert(u->mixer_handle);
|
||||
|
||||
if (u->ucm_context) {
|
||||
pa_alsa_ucm_port_data *data = PA_DEVICE_PORT_DATA(s->active_port);
|
||||
if (pa_alsa_ucm_port_device_status(data) <= 0)
|
||||
return;
|
||||
}
|
||||
|
||||
pa_alsa_path_set_mute(u->mixer_path, u->mixer_handle, s->muted);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue