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

ALSA: usb-audio: Introduce USB SND platform op callbacks

Allow for different platforms to be notified on USB SND connect/disconnect
sequences. This allows for platform USB SND modules to properly initialize
and populate internal structures with references to the USB SND chip
device.

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-13-quic_wcheng@quicinc.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Wesley Cheng and committed by
Greg Kroah-Hartman
74914dc1 f15d1e55

+59
+49
sound/usb/card.c
··· 118 118 static DEFINE_MUTEX(register_mutex); 119 119 static struct snd_usb_audio *usb_chip[SNDRV_CARDS]; 120 120 static struct usb_driver usb_audio_driver; 121 + static struct snd_usb_platform_ops *platform_ops; 122 + 123 + /* 124 + * Register platform specific operations that will be notified on events 125 + * which occur in USB SND. The platform driver can utilize this path to 126 + * enable features, such as USB audio offloading, which allows for audio data 127 + * to be queued by an audio DSP. 128 + * 129 + * Only one set of platform operations can be registered to USB SND. The 130 + * platform register operation is protected by the register_mutex. 131 + */ 132 + int snd_usb_register_platform_ops(struct snd_usb_platform_ops *ops) 133 + { 134 + guard(mutex)(&register_mutex); 135 + if (platform_ops) 136 + return -EEXIST; 137 + 138 + platform_ops = ops; 139 + return 0; 140 + } 141 + EXPORT_SYMBOL_GPL(snd_usb_register_platform_ops); 142 + 143 + /* 144 + * Unregisters the current set of platform operations. This allows for 145 + * a new set to be registered if required. 146 + * 147 + * The platform unregister operation is protected by the register_mutex. 148 + */ 149 + int snd_usb_unregister_platform_ops(void) 150 + { 151 + guard(mutex)(&register_mutex); 152 + platform_ops = NULL; 153 + 154 + return 0; 155 + } 156 + EXPORT_SYMBOL_GPL(snd_usb_unregister_platform_ops); 121 157 122 158 /* 123 159 * Checks to see if requested audio profile, i.e sample rate, # of ··· 990 954 chip->num_interfaces++; 991 955 usb_set_intfdata(intf, chip); 992 956 atomic_dec(&chip->active); 957 + 958 + if (platform_ops && platform_ops->connect_cb) 959 + platform_ops->connect_cb(chip); 993 960 mutex_unlock(&register_mutex); 961 + 994 962 return 0; 995 963 996 964 __error: ··· 1031 991 card = chip->card; 1032 992 1033 993 mutex_lock(&register_mutex); 994 + if (platform_ops && platform_ops->disconnect_cb) 995 + platform_ops->disconnect_cb(chip); 996 + 1034 997 if (atomic_inc_return(&chip->shutdown) == 1) { 1035 998 struct snd_usb_stream *as; 1036 999 struct snd_usb_endpoint *ep; ··· 1181 1138 chip->system_suspend = chip->num_suspended_intf; 1182 1139 } 1183 1140 1141 + if (platform_ops && platform_ops->suspend_cb) 1142 + platform_ops->suspend_cb(intf, message); 1143 + 1184 1144 return 0; 1185 1145 } 1186 1146 ··· 1223 1177 } 1224 1178 1225 1179 snd_usb_midi_v2_resume_all(chip); 1180 + 1181 + if (platform_ops && platform_ops->resume_cb) 1182 + platform_ops->resume_cb(intf); 1226 1183 1227 1184 out: 1228 1185 if (chip->num_suspended_intf == chip->system_suspend) {
+10
sound/usb/card.h
··· 209 209 struct list_head list; 210 210 }; 211 211 212 + struct snd_usb_platform_ops { 213 + void (*connect_cb)(struct snd_usb_audio *chip); 214 + void (*disconnect_cb)(struct snd_usb_audio *chip); 215 + void (*suspend_cb)(struct usb_interface *intf, pm_message_t message); 216 + void (*resume_cb)(struct usb_interface *intf); 217 + }; 218 + 212 219 struct snd_usb_stream * 213 220 snd_usb_find_suppported_substream(int card_idx, struct snd_pcm_hw_params *params, 214 221 int direction); 222 + 223 + int snd_usb_register_platform_ops(struct snd_usb_platform_ops *ops); 224 + int snd_usb_unregister_platform_ops(void); 215 225 #endif /* __USBAUDIO_CARD_H */