ALSA: usb-audio: Export USB SND APIs for modules
Some vendor modules will utilize useful parsing and endpoint management APIs to start audio playback/capture. Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Tested-by: Puma Hsu <pumahsu@google.com> Tested-by: Daehwan Jung <dh10.jung@samsung.com> Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com> Acked-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20250409194804.3773260-9-quic_wcheng@quicinc.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>pull/1259/head
parent
67890d5794
commit
5a49a6ba22
|
|
@ -1030,6 +1030,7 @@ int snd_usb_lock_shutdown(struct snd_usb_audio *chip)
|
||||||
wake_up(&chip->shutdown_wait);
|
wake_up(&chip->shutdown_wait);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_usb_lock_shutdown);
|
||||||
|
|
||||||
/* autosuspend and unlock the shutdown */
|
/* autosuspend and unlock the shutdown */
|
||||||
void snd_usb_unlock_shutdown(struct snd_usb_audio *chip)
|
void snd_usb_unlock_shutdown(struct snd_usb_audio *chip)
|
||||||
|
|
@ -1038,6 +1039,7 @@ void snd_usb_unlock_shutdown(struct snd_usb_audio *chip)
|
||||||
if (atomic_dec_and_test(&chip->usage_count))
|
if (atomic_dec_and_test(&chip->usage_count))
|
||||||
wake_up(&chip->shutdown_wait);
|
wake_up(&chip->shutdown_wait);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_usb_unlock_shutdown);
|
||||||
|
|
||||||
int snd_usb_autoresume(struct snd_usb_audio *chip)
|
int snd_usb_autoresume(struct snd_usb_audio *chip)
|
||||||
{
|
{
|
||||||
|
|
@ -1060,6 +1062,7 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_usb_autoresume);
|
||||||
|
|
||||||
void snd_usb_autosuspend(struct snd_usb_audio *chip)
|
void snd_usb_autosuspend(struct snd_usb_audio *chip)
|
||||||
{
|
{
|
||||||
|
|
@ -1073,6 +1076,7 @@ void snd_usb_autosuspend(struct snd_usb_audio *chip)
|
||||||
for (i = 0; i < chip->num_interfaces; i++)
|
for (i = 0; i < chip->num_interfaces; i++)
|
||||||
usb_autopm_put_interface(chip->intf[i]);
|
usb_autopm_put_interface(chip->intf[i]);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_usb_autosuspend);
|
||||||
|
|
||||||
static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
|
static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1524,6 +1524,7 @@ unlock:
|
||||||
mutex_unlock(&chip->mutex);
|
mutex_unlock(&chip->mutex);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_usb_endpoint_prepare);
|
||||||
|
|
||||||
/* get the current rate set to the given clock by any endpoint */
|
/* get the current rate set to the given clock by any endpoint */
|
||||||
int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock)
|
int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock)
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ void *snd_usb_find_csint_desc(void *buffer, int buflen, void *after, u8 dsubtype
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_usb_find_csint_desc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wrapper for usb_control_msg().
|
* Wrapper for usb_control_msg().
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,16 @@ find_format(struct list_head *fmt_list_head, snd_pcm_format_t format,
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct audioformat *
|
||||||
|
snd_usb_find_format(struct list_head *fmt_list_head, snd_pcm_format_t format,
|
||||||
|
unsigned int rate, unsigned int channels, bool strict_match,
|
||||||
|
struct snd_usb_substream *subs)
|
||||||
|
{
|
||||||
|
return find_format(fmt_list_head, format, rate, channels, strict_match,
|
||||||
|
subs);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_usb_find_format);
|
||||||
|
|
||||||
static const struct audioformat *
|
static const struct audioformat *
|
||||||
find_substream_format(struct snd_usb_substream *subs,
|
find_substream_format(struct snd_usb_substream *subs,
|
||||||
const struct snd_pcm_hw_params *params)
|
const struct snd_pcm_hw_params *params)
|
||||||
|
|
@ -157,6 +167,14 @@ find_substream_format(struct snd_usb_substream *subs,
|
||||||
true, subs);
|
true, subs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct audioformat *
|
||||||
|
snd_usb_find_substream_format(struct snd_usb_substream *subs,
|
||||||
|
const struct snd_pcm_hw_params *params)
|
||||||
|
{
|
||||||
|
return find_substream_format(subs, params);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_usb_find_substream_format);
|
||||||
|
|
||||||
bool snd_usb_pcm_has_fixed_rate(struct snd_usb_substream *subs)
|
bool snd_usb_pcm_has_fixed_rate(struct snd_usb_substream *subs)
|
||||||
{
|
{
|
||||||
const struct audioformat *fp;
|
const struct audioformat *fp;
|
||||||
|
|
@ -461,20 +479,9 @@ static void close_endpoints(struct snd_usb_audio *chip,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
int snd_usb_hw_params(struct snd_usb_substream *subs,
|
||||||
* hw_params callback
|
|
||||||
*
|
|
||||||
* allocate a buffer and set the given audio format.
|
|
||||||
*
|
|
||||||
* so far we use a physically linear buffer although packetize transfer
|
|
||||||
* doesn't need a continuous area.
|
|
||||||
* if sg buffer is supported on the later version of alsa, we'll follow
|
|
||||||
* that.
|
|
||||||
*/
|
|
||||||
static int snd_usb_hw_params(struct snd_pcm_substream *substream,
|
|
||||||
struct snd_pcm_hw_params *hw_params)
|
struct snd_pcm_hw_params *hw_params)
|
||||||
{
|
{
|
||||||
struct snd_usb_substream *subs = substream->runtime->private_data;
|
|
||||||
struct snd_usb_audio *chip = subs->stream->chip;
|
struct snd_usb_audio *chip = subs->stream->chip;
|
||||||
const struct audioformat *fmt;
|
const struct audioformat *fmt;
|
||||||
const struct audioformat *sync_fmt;
|
const struct audioformat *sync_fmt;
|
||||||
|
|
@ -499,7 +506,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
|
||||||
if (fmt->implicit_fb) {
|
if (fmt->implicit_fb) {
|
||||||
sync_fmt = snd_usb_find_implicit_fb_sync_format(chip, fmt,
|
sync_fmt = snd_usb_find_implicit_fb_sync_format(chip, fmt,
|
||||||
hw_params,
|
hw_params,
|
||||||
!substream->stream,
|
!subs->direction,
|
||||||
&sync_fixed_rate);
|
&sync_fixed_rate);
|
||||||
if (!sync_fmt) {
|
if (!sync_fmt) {
|
||||||
usb_audio_dbg(chip,
|
usb_audio_dbg(chip,
|
||||||
|
|
@ -579,15 +586,28 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_usb_hw_params);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* hw_free callback
|
* hw_params callback
|
||||||
*
|
*
|
||||||
* reset the audio format and release the buffer
|
* allocate a buffer and set the given audio format.
|
||||||
|
*
|
||||||
|
* so far we use a physically linear buffer although packetize transfer
|
||||||
|
* doesn't need a continuous area.
|
||||||
|
* if sg buffer is supported on the later version of alsa, we'll follow
|
||||||
|
* that.
|
||||||
*/
|
*/
|
||||||
static int snd_usb_hw_free(struct snd_pcm_substream *substream)
|
static int snd_usb_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||||
|
struct snd_pcm_hw_params *hw_params)
|
||||||
{
|
{
|
||||||
struct snd_usb_substream *subs = substream->runtime->private_data;
|
struct snd_usb_substream *subs = substream->runtime->private_data;
|
||||||
|
|
||||||
|
return snd_usb_hw_params(subs, hw_params);
|
||||||
|
}
|
||||||
|
|
||||||
|
int snd_usb_hw_free(struct snd_usb_substream *subs)
|
||||||
|
{
|
||||||
struct snd_usb_audio *chip = subs->stream->chip;
|
struct snd_usb_audio *chip = subs->stream->chip;
|
||||||
|
|
||||||
snd_media_stop_pipeline(subs);
|
snd_media_stop_pipeline(subs);
|
||||||
|
|
@ -603,6 +623,19 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_usb_hw_free);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hw_free callback
|
||||||
|
*
|
||||||
|
* reset the audio format and release the buffer
|
||||||
|
*/
|
||||||
|
static int snd_usb_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||||
|
{
|
||||||
|
struct snd_usb_substream *subs = substream->runtime->private_data;
|
||||||
|
|
||||||
|
return snd_usb_hw_free(subs);
|
||||||
|
}
|
||||||
|
|
||||||
/* free-wheeling mode? (e.g. dmix) */
|
/* free-wheeling mode? (e.g. dmix) */
|
||||||
static int in_free_wheeling_mode(struct snd_pcm_runtime *runtime)
|
static int in_free_wheeling_mode(struct snd_pcm_runtime *runtime)
|
||||||
|
|
@ -1746,8 +1779,8 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
|
||||||
static const struct snd_pcm_ops snd_usb_playback_ops = {
|
static const struct snd_pcm_ops snd_usb_playback_ops = {
|
||||||
.open = snd_usb_pcm_open,
|
.open = snd_usb_pcm_open,
|
||||||
.close = snd_usb_pcm_close,
|
.close = snd_usb_pcm_close,
|
||||||
.hw_params = snd_usb_hw_params,
|
.hw_params = snd_usb_pcm_hw_params,
|
||||||
.hw_free = snd_usb_hw_free,
|
.hw_free = snd_usb_pcm_hw_free,
|
||||||
.prepare = snd_usb_pcm_prepare,
|
.prepare = snd_usb_pcm_prepare,
|
||||||
.trigger = snd_usb_substream_playback_trigger,
|
.trigger = snd_usb_substream_playback_trigger,
|
||||||
.sync_stop = snd_usb_pcm_sync_stop,
|
.sync_stop = snd_usb_pcm_sync_stop,
|
||||||
|
|
@ -1758,8 +1791,8 @@ static const struct snd_pcm_ops snd_usb_playback_ops = {
|
||||||
static const struct snd_pcm_ops snd_usb_capture_ops = {
|
static const struct snd_pcm_ops snd_usb_capture_ops = {
|
||||||
.open = snd_usb_pcm_open,
|
.open = snd_usb_pcm_open,
|
||||||
.close = snd_usb_pcm_close,
|
.close = snd_usb_pcm_close,
|
||||||
.hw_params = snd_usb_hw_params,
|
.hw_params = snd_usb_pcm_hw_params,
|
||||||
.hw_free = snd_usb_hw_free,
|
.hw_free = snd_usb_pcm_hw_free,
|
||||||
.prepare = snd_usb_pcm_prepare,
|
.prepare = snd_usb_pcm_prepare,
|
||||||
.trigger = snd_usb_substream_capture_trigger,
|
.trigger = snd_usb_substream_capture_trigger,
|
||||||
.sync_stop = snd_usb_pcm_sync_stop,
|
.sync_stop = snd_usb_pcm_sync_stop,
|
||||||
|
|
|
||||||
|
|
@ -15,4 +15,15 @@ void snd_usb_preallocate_buffer(struct snd_usb_substream *subs);
|
||||||
int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip,
|
int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip,
|
||||||
struct audioformat *fmt);
|
struct audioformat *fmt);
|
||||||
|
|
||||||
|
const struct audioformat *
|
||||||
|
snd_usb_find_format(struct list_head *fmt_list_head, snd_pcm_format_t format,
|
||||||
|
unsigned int rate, unsigned int channels, bool strict_match,
|
||||||
|
struct snd_usb_substream *subs);
|
||||||
|
const struct audioformat *
|
||||||
|
snd_usb_find_substream_format(struct snd_usb_substream *subs,
|
||||||
|
const struct snd_pcm_hw_params *params);
|
||||||
|
|
||||||
|
int snd_usb_hw_params(struct snd_usb_substream *subs,
|
||||||
|
struct snd_pcm_hw_params *hw_params);
|
||||||
|
int snd_usb_hw_free(struct snd_usb_substream *subs);
|
||||||
#endif /* __USBAUDIO_PCM_H */
|
#endif /* __USBAUDIO_PCM_H */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue