On 8/29/24 21:41, Wesley Cheng wrote: > In order to allow userspace/applications know about USB offloading status, > expose a sound kcontrol that fetches information about which sound card > and PCM index the USB device is mapped to for supporting offloading. In > the USB audio offloading framework, the ASoC BE DAI link is the entity > responsible for registering to the SOC USB layer. > > It is expected for the USB SND offloading driver to add the kcontrol to the > sound card associated with the USB audio device. An example output would > look like: this is very odd, the offloading driver adds a control to another card? That seems like a rather important layering violation. I thought it was done the other way, the USB audio card created a control that would point to the other card/device. > > tinymix -D 1 get 'USB Offload Playback Route PCM#0' > -1, -1 (range -1->255) > > This example signifies that there is no mapped ASoC path available for the > USB SND device. but that control would not even exist if the ASoC-based driver isn't probed. It's become really hard to follow, I've been on all this for 1.5hrs and losing track of the design. > tinymix -D 1 get 'USB Offload Playback Route PCM#0' > 0, 0 (range -1->255) > > This example signifies that the offload path is available over ASoC sound > card index#0 and PCM device#0. > > Signed-off-by: Wesley Cheng <quic_wcheng@xxxxxxxxxxx> > --- > sound/usb/Kconfig | 10 +++ > sound/usb/Makefile | 2 + > sound/usb/mixer_usb_offload.c | 102 ++++++++++++++++++++++++++++++ > sound/usb/mixer_usb_offload.h | 17 +++++ > sound/usb/qcom/Makefile | 2 +- > sound/usb/qcom/qc_audio_offload.c | 2 + > 6 files changed, 134 insertions(+), 1 deletion(-) > create mode 100644 sound/usb/mixer_usb_offload.c > create mode 100644 sound/usb/mixer_usb_offload.h > > diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig > index 5cc3eaf53e6b..e3fbf9541d0b 100644 > --- a/sound/usb/Kconfig > +++ b/sound/usb/Kconfig > @@ -176,10 +176,20 @@ config SND_BCD2000 > To compile this driver as a module, choose M here: the module > will be called snd-bcd2000. > > +config SND_USB_OFFLOAD_MIXER > + tristate "USB Audio Offload mixer control" > + help > + Say Y to enable the USB audio offloading mixer controls. This > + exposes an USB offload capable kcontrol to signal to applications > + about which platform sound card can support USB audio offload. > + The returning values specify the mapped ASoC card and PCM device > + the USB audio device is associated to. > + > config SND_USB_AUDIO_QMI > tristate "Qualcomm Audio Offload driver" > depends on QCOM_QMI_HELPERS && SND_USB_AUDIO && USB_XHCI_SIDEBAND && SND_SOC_USB > select SND_PCM > + select SND_USB_OFFLOAD_MIXER > help > Say Y here to enable the Qualcomm USB audio offloading feature. > > diff --git a/sound/usb/Makefile b/sound/usb/Makefile > index 54a06a2f73ca..2f19f854944c 100644 > --- a/sound/usb/Makefile > +++ b/sound/usb/Makefile > @@ -36,3 +36,5 @@ obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o > > obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/ bcd2000/ qcom/ > obj-$(CONFIG_SND_USB_LINE6) += line6/ > + > +obj-$(CONFIG_SND_USB_OFFLOAD_MIXER) += mixer_usb_offload.o > diff --git a/sound/usb/mixer_usb_offload.c b/sound/usb/mixer_usb_offload.c > new file mode 100644 > index 000000000000..16e2fd634684 > --- /dev/null > +++ b/sound/usb/mixer_usb_offload.c > @@ -0,0 +1,102 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. > + */ > + > +#include <linux/usb.h> > + > +#include <sound/core.h> > +#include <sound/control.h> > +#include <sound/soc-usb.h> > + > +#include "usbaudio.h" > +#include "card.h" > +#include "helper.h" > +#include "mixer.h" > + > +#include "mixer_usb_offload.h" > + > +#define PCM_IDX(n) ((n) & 0xffff) > +#define CARD_IDX(n) ((n) >> 16) > + > +static int > +snd_usb_offload_route_get(struct snd_kcontrol *kcontrol, > + struct snd_ctl_elem_value *ucontrol) > +{ > + struct device *sysdev = snd_kcontrol_chip(kcontrol); > + int ret; > + > + ret = snd_soc_usb_update_offload_route(sysdev, > + CARD_IDX(kcontrol->private_value), > + PCM_IDX(kcontrol->private_value), > + SNDRV_PCM_STREAM_PLAYBACK, > + ucontrol->value.integer.value); > + if (ret < 0) { > + ucontrol->value.integer.value[0] = -1; > + ucontrol->value.integer.value[1] = -1; > + } > + > + return 0; > +} > + > +static int snd_usb_offload_route_info(struct snd_kcontrol *kcontrol, > + struct snd_ctl_elem_info *uinfo) > +{ > + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; > + uinfo->count = 2; > + uinfo->value.integer.min = -1; > + /* Arbitrary max value, as there is no 'limit' on number of PCM devices */ > + uinfo->value.integer.max = 0xff; > + > + return 0; > +} > + > +static struct snd_kcontrol_new snd_usb_offload_mapped_ctl = { > + .iface = SNDRV_CTL_ELEM_IFACE_CARD, > + .access = SNDRV_CTL_ELEM_ACCESS_READ, > + .info = snd_usb_offload_route_info, > + .get = snd_usb_offload_route_get, > +}; > + > +/** > + * snd_usb_offload_create_ctl() - Add USB offload bounded mixer > + * @chip - USB SND chip device > + * > + * Creates a sound control for a USB audio device, so that applications can > + * query for if there is an available USB audio offload path, and which > + * card is managing it. > + */ > +int snd_usb_offload_create_ctl(struct snd_usb_audio *chip) > +{ > + struct usb_device *udev = chip->dev; > + struct snd_kcontrol_new *chip_kctl; > + struct snd_usb_substream *subs; > + struct snd_usb_stream *as; > + char ctl_name[37]; > + int ret; > + > + list_for_each_entry(as, &chip->pcm_list, list) { > + subs = &as->substream[SNDRV_PCM_STREAM_PLAYBACK]; > + if (!subs->ep_num) > + continue; > + > + chip_kctl = &snd_usb_offload_mapped_ctl; > + chip_kctl->count = 1; > + /* > + * Store the associated USB SND card number and PCM index for > + * the kctl. > + */ > + chip_kctl->private_value = as->pcm_index | > + chip->card->number << 16; > + sprintf(ctl_name, "USB Offload Playback Route PCM#%d", > + as->pcm_index); > + chip_kctl->name = ctl_name; > + ret = snd_ctl_add(chip->card, snd_ctl_new1(chip_kctl, > + udev->bus->sysdev)); > + if (ret < 0) > + break; > + } > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(snd_usb_offload_create_ctl); > diff --git a/sound/usb/mixer_usb_offload.h b/sound/usb/mixer_usb_offload.h > new file mode 100644 > index 000000000000..3f6e2a8b19c8 > --- /dev/null > +++ b/sound/usb/mixer_usb_offload.h > @@ -0,0 +1,17 @@ > +/* SPDX-License-Identifier: GPL-2.0 > + * > + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. > + */ > + > +#ifndef __USB_OFFLOAD_MIXER_H > +#define __USB_OFFLOAD_MIXER_H > + > +#if IS_ENABLED(CONFIG_SND_USB_OFFLOAD_MIXER) > +int snd_usb_offload_create_ctl(struct snd_usb_audio *chip); > +#else > +static inline int snd_usb_offload_create_ctl(struct snd_usb_audio *chip) > +{ > + return 0; > +} > +#endif > +#endif /* __USB_OFFLOAD_MIXER_H */ > diff --git a/sound/usb/qcom/Makefile b/sound/usb/qcom/Makefile > index a81c9b28d484..4005e8391ab9 100644 > --- a/sound/usb/qcom/Makefile > +++ b/sound/usb/qcom/Makefile > @@ -1,2 +1,2 @@ > snd-usb-audio-qmi-objs := usb_audio_qmi_v01.o qc_audio_offload.o > -obj-$(CONFIG_SND_USB_AUDIO_QMI) += snd-usb-audio-qmi.o > \ No newline at end of file > +obj-$(CONFIG_SND_USB_AUDIO_QMI) += snd-usb-audio-qmi.o > diff --git a/sound/usb/qcom/qc_audio_offload.c b/sound/usb/qcom/qc_audio_offload.c > index a7ad15404fd1..5b9262a116be 100644 > --- a/sound/usb/qcom/qc_audio_offload.c > +++ b/sound/usb/qcom/qc_audio_offload.c > @@ -36,6 +36,7 @@ > #include "../helper.h" > #include "../pcm.h" > #include "../power.h" > +#include "../mixer_usb_offload.h" > > #include "usb_audio_qmi_v01.h" > > @@ -1703,6 +1704,7 @@ static void qc_usb_audio_offload_probe(struct snd_usb_audio *chip) > sdev->card_idx = chip->card->number; > sdev->chip_idx = chip->index; > > + snd_usb_offload_create_ctl(chip); > snd_soc_usb_connect(usb_get_usb_backend(udev), sdev); > } >