Hi Pierre, On 8/30/2024 3:05 AM, Pierre-Louis Bossart wrote: > > 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. The USB SND offloading vendor driver (qc_audio_offload), which technically co-exists with USB SND core, is the entity that will add the offload kcontrol to the USB audio device's sound card. Initially, I had the kcontrol creation as part of the USB SND mixer, but I believe Takashi preferred if the vendor driver did it instead. > >> 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. Hence why it probably is a good idea to leave it within the USB offload vendor driver. There are checks to ensure that the ASoC based driver is probed/available before the kcontrols are created for a device. If there are devices that were identified before the ASoC components were probed, then the snd_usb_rediscover_devices() is triggered as part of soc-usb, and that would call the connect_cb() callback to the USB SND vendor offload driver to create the kcontrol. Thanks Wesley Cheng >> 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); >> } >>