Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Wesley Cheng and committed by
Greg Kroah-Hartman
5a49a6ba 67890d57

+71 -21
+4
sound/usb/card.c
··· 1030 1030 wake_up(&chip->shutdown_wait); 1031 1031 return err; 1032 1032 } 1033 + EXPORT_SYMBOL_GPL(snd_usb_lock_shutdown); 1033 1034 1034 1035 /* autosuspend and unlock the shutdown */ 1035 1036 void snd_usb_unlock_shutdown(struct snd_usb_audio *chip) ··· 1039 1038 if (atomic_dec_and_test(&chip->usage_count)) 1040 1039 wake_up(&chip->shutdown_wait); 1041 1040 } 1041 + EXPORT_SYMBOL_GPL(snd_usb_unlock_shutdown); 1042 1042 1043 1043 int snd_usb_autoresume(struct snd_usb_audio *chip) 1044 1044 { ··· 1062 1060 } 1063 1061 return 0; 1064 1062 } 1063 + EXPORT_SYMBOL_GPL(snd_usb_autoresume); 1065 1064 1066 1065 void snd_usb_autosuspend(struct snd_usb_audio *chip) 1067 1066 { ··· 1076 1073 for (i = 0; i < chip->num_interfaces; i++) 1077 1074 usb_autopm_put_interface(chip->intf[i]); 1078 1075 } 1076 + EXPORT_SYMBOL_GPL(snd_usb_autosuspend); 1079 1077 1080 1078 static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) 1081 1079 {
+1
sound/usb/endpoint.c
··· 1524 1524 mutex_unlock(&chip->mutex); 1525 1525 return err; 1526 1526 } 1527 + EXPORT_SYMBOL_GPL(snd_usb_endpoint_prepare); 1527 1528 1528 1529 /* get the current rate set to the given clock by any endpoint */ 1529 1530 int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock)
+1
sound/usb/helper.c
··· 62 62 } 63 63 return NULL; 64 64 } 65 + EXPORT_SYMBOL_GPL(snd_usb_find_csint_desc); 65 66 66 67 /* 67 68 * Wrapper for usb_control_msg().
+54 -21
sound/usb/pcm.c
··· 148 148 return found; 149 149 } 150 150 151 + const struct audioformat * 152 + snd_usb_find_format(struct list_head *fmt_list_head, snd_pcm_format_t format, 153 + unsigned int rate, unsigned int channels, bool strict_match, 154 + struct snd_usb_substream *subs) 155 + { 156 + return find_format(fmt_list_head, format, rate, channels, strict_match, 157 + subs); 158 + } 159 + EXPORT_SYMBOL_GPL(snd_usb_find_format); 160 + 151 161 static const struct audioformat * 152 162 find_substream_format(struct snd_usb_substream *subs, 153 163 const struct snd_pcm_hw_params *params) ··· 166 156 params_rate(params), params_channels(params), 167 157 true, subs); 168 158 } 159 + 160 + const struct audioformat * 161 + snd_usb_find_substream_format(struct snd_usb_substream *subs, 162 + const struct snd_pcm_hw_params *params) 163 + { 164 + return find_substream_format(subs, params); 165 + } 166 + EXPORT_SYMBOL_GPL(snd_usb_find_substream_format); 169 167 170 168 bool snd_usb_pcm_has_fixed_rate(struct snd_usb_substream *subs) 171 169 { ··· 479 461 } 480 462 } 481 463 482 - /* 483 - * hw_params callback 484 - * 485 - * allocate a buffer and set the given audio format. 486 - * 487 - * so far we use a physically linear buffer although packetize transfer 488 - * doesn't need a continuous area. 489 - * if sg buffer is supported on the later version of alsa, we'll follow 490 - * that. 491 - */ 492 - static int snd_usb_hw_params(struct snd_pcm_substream *substream, 493 - struct snd_pcm_hw_params *hw_params) 464 + int snd_usb_hw_params(struct snd_usb_substream *subs, 465 + struct snd_pcm_hw_params *hw_params) 494 466 { 495 - struct snd_usb_substream *subs = substream->runtime->private_data; 496 467 struct snd_usb_audio *chip = subs->stream->chip; 497 468 const struct audioformat *fmt; 498 469 const struct audioformat *sync_fmt; ··· 506 499 if (fmt->implicit_fb) { 507 500 sync_fmt = snd_usb_find_implicit_fb_sync_format(chip, fmt, 508 501 hw_params, 509 - !substream->stream, 502 + !subs->direction, 510 503 &sync_fixed_rate); 511 504 if (!sync_fmt) { 512 505 usb_audio_dbg(chip, ··· 586 579 587 580 return ret; 588 581 } 582 + EXPORT_SYMBOL_GPL(snd_usb_hw_params); 589 583 590 584 /* 591 - * hw_free callback 585 + * hw_params callback 592 586 * 593 - * reset the audio format and release the buffer 587 + * allocate a buffer and set the given audio format. 588 + * 589 + * so far we use a physically linear buffer although packetize transfer 590 + * doesn't need a continuous area. 591 + * if sg buffer is supported on the later version of alsa, we'll follow 592 + * that. 594 593 */ 595 - static int snd_usb_hw_free(struct snd_pcm_substream *substream) 594 + static int snd_usb_pcm_hw_params(struct snd_pcm_substream *substream, 595 + struct snd_pcm_hw_params *hw_params) 596 596 { 597 597 struct snd_usb_substream *subs = substream->runtime->private_data; 598 + 599 + return snd_usb_hw_params(subs, hw_params); 600 + } 601 + 602 + int snd_usb_hw_free(struct snd_usb_substream *subs) 603 + { 598 604 struct snd_usb_audio *chip = subs->stream->chip; 599 605 600 606 snd_media_stop_pipeline(subs); ··· 622 602 } 623 603 624 604 return 0; 605 + } 606 + EXPORT_SYMBOL_GPL(snd_usb_hw_free); 607 + 608 + /* 609 + * hw_free callback 610 + * 611 + * reset the audio format and release the buffer 612 + */ 613 + static int snd_usb_pcm_hw_free(struct snd_pcm_substream *substream) 614 + { 615 + struct snd_usb_substream *subs = substream->runtime->private_data; 616 + 617 + return snd_usb_hw_free(subs); 625 618 } 626 619 627 620 /* free-wheeling mode? (e.g. dmix) */ ··· 1779 1746 static const struct snd_pcm_ops snd_usb_playback_ops = { 1780 1747 .open = snd_usb_pcm_open, 1781 1748 .close = snd_usb_pcm_close, 1782 - .hw_params = snd_usb_hw_params, 1783 - .hw_free = snd_usb_hw_free, 1749 + .hw_params = snd_usb_pcm_hw_params, 1750 + .hw_free = snd_usb_pcm_hw_free, 1784 1751 .prepare = snd_usb_pcm_prepare, 1785 1752 .trigger = snd_usb_substream_playback_trigger, 1786 1753 .sync_stop = snd_usb_pcm_sync_stop, ··· 1791 1758 static const struct snd_pcm_ops snd_usb_capture_ops = { 1792 1759 .open = snd_usb_pcm_open, 1793 1760 .close = snd_usb_pcm_close, 1794 - .hw_params = snd_usb_hw_params, 1795 - .hw_free = snd_usb_hw_free, 1761 + .hw_params = snd_usb_pcm_hw_params, 1762 + .hw_free = snd_usb_pcm_hw_free, 1796 1763 .prepare = snd_usb_pcm_prepare, 1797 1764 .trigger = snd_usb_substream_capture_trigger, 1798 1765 .sync_stop = snd_usb_pcm_sync_stop,
+11
sound/usb/pcm.h
··· 15 15 int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip, 16 16 struct audioformat *fmt); 17 17 18 + const struct audioformat * 19 + snd_usb_find_format(struct list_head *fmt_list_head, snd_pcm_format_t format, 20 + unsigned int rate, unsigned int channels, bool strict_match, 21 + struct snd_usb_substream *subs); 22 + const struct audioformat * 23 + snd_usb_find_substream_format(struct snd_usb_substream *subs, 24 + const struct snd_pcm_hw_params *params); 25 + 26 + int snd_usb_hw_params(struct snd_usb_substream *subs, 27 + struct snd_pcm_hw_params *hw_params); 28 + int snd_usb_hw_free(struct snd_usb_substream *subs); 18 29 #endif /* __USBAUDIO_PCM_H */