Commit a0a4959e authored by Jorge Sanjuan's avatar Jorge Sanjuan Committed by Takashi Iwai

ALSA: usb-audio: Operate UAC3 Power Domains in PCM callbacks

Make use of UAC3 Power Domains associated to an Audio Streaming
path within the PCM's logic. This means, when there is no audio
being transferred (pcm is closed), the host will set the Power Domain
associated to that substream to state D1. When audio is being transferred
(from hw_params onwards), the Power Domain will be set to D0 state.

This is the way the host lets the device know which Terminal
is going to be actively used and it is for the device to
manage its own internal resources on that UAC3 Power Domain.

Note the resume method now sets the Power Domain to D1 state as
resuming the device doesn't mean audio streaming will occur.
Signed-off-by: default avatarJorge Sanjuan <jorge.sanjuan@codethink.co.uk>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 3f59aa11
...@@ -748,11 +748,11 @@ int snd_usb_pcm_resume(struct snd_usb_stream *as) ...@@ -748,11 +748,11 @@ int snd_usb_pcm_resume(struct snd_usb_stream *as)
{ {
int ret; int ret;
ret = snd_usb_pcm_change_state(&as->substream[0], UAC3_PD_STATE_D0); ret = snd_usb_pcm_change_state(&as->substream[0], UAC3_PD_STATE_D1);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = snd_usb_pcm_change_state(&as->substream[1], UAC3_PD_STATE_D0); ret = snd_usb_pcm_change_state(&as->substream[1], UAC3_PD_STATE_D1);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -803,16 +803,22 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, ...@@ -803,16 +803,22 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
ret = snd_usb_lock_shutdown(subs->stream->chip); ret = snd_usb_lock_shutdown(subs->stream->chip);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0);
if (ret < 0)
goto unlock;
ret = set_format(subs, fmt); ret = set_format(subs, fmt);
snd_usb_unlock_shutdown(subs->stream->chip);
if (ret < 0) if (ret < 0)
return ret; goto unlock;
subs->interface = fmt->iface; subs->interface = fmt->iface;
subs->altset_idx = fmt->altset_idx; subs->altset_idx = fmt->altset_idx;
subs->need_setup_ep = true; subs->need_setup_ep = true;
return 0; unlock:
snd_usb_unlock_shutdown(subs->stream->chip);
return ret;
} }
/* /*
...@@ -869,6 +875,10 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) ...@@ -869,6 +875,10 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint);
snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); snd_usb_endpoint_sync_pending_stop(subs->data_endpoint);
ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0);
if (ret < 0)
goto unlock;
ret = set_format(subs, subs->cur_audiofmt); ret = set_format(subs, subs->cur_audiofmt);
if (ret < 0) if (ret < 0)
goto unlock; goto unlock;
...@@ -1313,6 +1323,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream) ...@@ -1313,6 +1323,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream)
int direction = substream->stream; int direction = substream->stream;
struct snd_usb_stream *as = snd_pcm_substream_chip(substream); struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
struct snd_usb_substream *subs = &as->substream[direction]; struct snd_usb_substream *subs = &as->substream[direction];
int ret;
stop_endpoints(subs, true); stop_endpoints(subs, true);
...@@ -1321,7 +1332,10 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream) ...@@ -1321,7 +1332,10 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream)
!snd_usb_lock_shutdown(subs->stream->chip)) { !snd_usb_lock_shutdown(subs->stream->chip)) {
usb_set_interface(subs->dev, subs->interface, 0); usb_set_interface(subs->dev, subs->interface, 0);
subs->interface = -1; subs->interface = -1;
ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D1);
snd_usb_unlock_shutdown(subs->stream->chip); snd_usb_unlock_shutdown(subs->stream->chip);
if (ret < 0)
return ret;
} }
subs->pcm_substream = NULL; subs->pcm_substream = NULL;
......
...@@ -110,8 +110,12 @@ static void snd_usb_init_substream(struct snd_usb_stream *as, ...@@ -110,8 +110,12 @@ static void snd_usb_init_substream(struct snd_usb_stream *as,
if (fp->channels > subs->channels_max) if (fp->channels > subs->channels_max)
subs->channels_max = fp->channels; subs->channels_max = fp->channels;
if (pd) if (pd) {
subs->str_pd = pd; subs->str_pd = pd;
/* Initialize Power Domain to idle status D1 */
snd_usb_power_domain_set(subs->stream->chip, pd,
UAC3_PD_STATE_D1);
}
snd_usb_preallocate_buffer(subs); snd_usb_preallocate_buffer(subs);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment