---
sound/usb/Kconfig | 4 ++
sound/usb/Makefile | 1 +
sound/usb/mixer.c | 5 +++
sound/usb/mixer_usb_offload.c | 72 +++++++++++++++++++++++++++++++++++
sound/usb/mixer_usb_offload.h | 17 +++++++++
5 files changed, 99 insertions(+)
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 4c842fbe6365..3e7be258d0e3 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -176,10 +176,14 @@ 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
+ bool
+
config SND_USB_AUDIO_QMI
tristate "Qualcomm Audio Offload driver"
depends on QCOM_QMI_HELPERS && SND_USB_AUDIO && USB_XHCI_SIDEBAND
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 246788268ddd..8c54660a11b0 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -22,6 +22,7 @@ snd-usb-audio-objs := card.o \
stream.o \
validate.o
+snd-usb-audio-$(CONFIG_SND_USB_OFFLOAD_MIXER) += mixer_usb_offload.o
snd-usb-audio-$(CONFIG_SND_USB_AUDIO_MIDI_V2) += midi2.o
snd-usb-audio-$(CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER) += media.o
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 409fc1164694..09229e623469 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -48,6 +48,7 @@
#include "mixer.h"
#include "helper.h"
#include "mixer_quirks.h"
+#include "mixer_usb_offload.h"
#include "power.h"
#define MAX_ID_ELEMS 256
@@ -3609,6 +3610,10 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif)
if (err < 0)
goto _error;
+ err = snd_usb_offload_init_mixer(mixer);
+ if (err < 0)
+ goto _error;
+
err = snd_device_new(chip->card, SNDRV_DEV_CODEC, mixer, &dev_ops);
if (err < 0)
goto _error;
diff --git a/sound/usb/mixer_usb_offload.c b/sound/usb/mixer_usb_offload.c
new file mode 100644
index 000000000000..61b17359b987
--- /dev/null
+++ b/sound/usb/mixer_usb_offload.c
@@ -0,0 +1,72 @@
+// 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 "card.h"
+#include "mixer.h"
+#include "mixer_usb_offload.h"
+#include "usbaudio.h"
+
+static int
+snd_usb_offload_create_mixer(struct usb_mixer_interface *mixer,
+ const struct snd_kcontrol_new *new_kctl)
+{
+ struct snd_usb_audio *chip = mixer->chip;
+ struct usb_device *udev = chip->dev;
+
+ return snd_ctl_add(chip->card,
+ snd_ctl_new1(new_kctl, udev->bus->sysdev));
+}
+
+static int
+snd_usb_offload_available_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct device *sysdev = snd_kcontrol_chip(kcontrol);
+ int ret;
+
+ ret = snd_soc_usb_device_offload_available(sysdev);
+ ucontrol->value.integer.value[0] = ret < 0 ? -1 : ret;
+
+ return ret < 0 ? ret : 0;
+}
+
+static int snd_usb_offload_available_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = -1;
+ uinfo->value.integer.max = SNDRV_CARDS;
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new snd_usb_offload_available_ctl = {
+ .iface = SNDRV_CTL_ELEM_IFACE_CARD,
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .name = "USB Offload Playback Capable Card",
+ .info = snd_usb_offload_available_info,
+ .get = snd_usb_offload_available_get,
+};
+
+/**
+ * snd_usb_offload_init_mixer() - Add USB offload bounded mixer
+ * @mixer - USB mixer
+ *
+ * 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_init_mixer(struct usb_mixer_interface *mixer)
+{
+ return snd_usb_offload_create_mixer(mixer, &snd_usb_offload_available_ctl);
+}
+EXPORT_SYMBOL_GPL(snd_usb_offload_init_mixer);
diff --git a/sound/usb/mixer_usb_offload.h b/sound/usb/mixer_usb_offload.h
new file mode 100644
index 000000000000..fb88e872d8fa
--- /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_init_mixer(struct usb_mixer_interface *mixer);
+#else
+static int snd_usb_offload_init_mixer(struct usb_mixer_interface *mixer)
+{
+ return 0;
+}
+#endif
+#endif /* __USB_OFFLOAD_MIXER_H */