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:
Alper Nebi Yasak 2023-11-25 12:31:11 +00:00
parent 3e2bb8a1ec
commit bafe545da7
4 changed files with 120 additions and 0 deletions

View file

@ -286,6 +286,10 @@ struct pa_alsa_ucm_port_data {
int eld_device; /* PCM device number */
};
int pa_alsa_ucm_port_device_enable(pa_alsa_ucm_port_data *data);
int pa_alsa_ucm_port_device_disable(pa_alsa_ucm_port_data *data);
long pa_alsa_ucm_port_device_status(pa_alsa_ucm_port_data *data);
struct pa_alsa_ucm_volume {
char *mixer_elem; /* mixer element identifier */
char *master_elem; /* master mixer element identifier */