diff options
author | Jorge Sanjuan <jorge.sanjuan@codethink.co.uk> | 2018-07-31 14:28:44 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2018-07-31 15:01:36 +0200 |
commit | 3f59aa11c6776da8d0f9f50c741ef02bfc4a8766 (patch) | |
tree | 525006d8010aedab1c17179c37dc2c379aacb22d /sound/usb/pcm.c | |
parent | ALSA: usb-audio: AudioStreaming Power Domain parsing (diff) | |
download | linux-3f59aa11c6776da8d0f9f50c741ef02bfc4a8766.tar.xz linux-3f59aa11c6776da8d0f9f50c741ef02bfc4a8766.zip |
ALSA: usb-audio: Add UAC3 Power Domains to suspend/resume
Set the UAC3 Power Domain state for an Audio Streaming interface
to D2 state before suspending the device (usb_driver callback).
This lets the device know there is no intention to use any of the
Units in the Audio Function and that the host is not going to
even listen for wake-up events (interrupts) on the units.
When the usb_driver gets resumed, the state D0 (fully powered) will
be set. This ties up the UAC3 Power Domains to the runtime PM.
Signed-off-by: Jorge Sanjuan <jorge.sanjuan@codethink.co.uk>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb/pcm.c')
-rw-r--r-- | sound/usb/pcm.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 4b930fa47277..99ec9d5caa58 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -711,6 +711,54 @@ static int configure_endpoint(struct snd_usb_substream *subs) return ret; } +static int snd_usb_pcm_change_state(struct snd_usb_substream *subs, int state) +{ + int ret; + + if (!subs->str_pd) + return 0; + + ret = snd_usb_power_domain_set(subs->stream->chip, subs->str_pd, state); + if (ret < 0) { + dev_err(&subs->dev->dev, + "Cannot change Power Domain ID: %d to state: %d. Err: %d\n", + subs->str_pd->pd_id, state, ret); + return ret; + } + + return 0; +} + +int snd_usb_pcm_suspend(struct snd_usb_stream *as) +{ + int ret; + + ret = snd_usb_pcm_change_state(&as->substream[0], UAC3_PD_STATE_D2); + if (ret < 0) + return ret; + + ret = snd_usb_pcm_change_state(&as->substream[1], UAC3_PD_STATE_D2); + if (ret < 0) + return ret; + + return 0; +} + +int snd_usb_pcm_resume(struct snd_usb_stream *as) +{ + int ret; + + ret = snd_usb_pcm_change_state(&as->substream[0], UAC3_PD_STATE_D0); + if (ret < 0) + return ret; + + ret = snd_usb_pcm_change_state(&as->substream[1], UAC3_PD_STATE_D0); + if (ret < 0) + return ret; + + return 0; +} + /* * hw_params callback * |