summaryrefslogtreecommitdiff
path: root/sound/soc/qcom/qdsp6
diff options
context:
space:
mode:
authorWesley Cheng <quic_wcheng@quicinc.com>2025-04-09 12:47:58 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-04-11 13:02:32 +0200
commit1b8d0d87b934f002a06a8ec2abfe907bd12e8cd4 (patch)
tree3631dc626fffedea0b54e60323cdfb3536246405 /sound/soc/qcom/qdsp6
parent72b0b8b2998043c50b191d9668c7a828ca0d5c70 (diff)
ASoC: qcom: qdsp6: Add headphone jack for offload connection status
The headphone jack framework has a well defined infrastructure for notifying userspace entities through input devices. Expose a jack device that carries information about if an offload capable device is connected. Applications can further identify specific offloading information through other SND kcontrols. Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com> Acked-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20250409194804.3773260-26-quic_wcheng@quicinc.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'sound/soc/qcom/qdsp6')
-rw-r--r--sound/soc/qcom/qdsp6/q6usb.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/sound/soc/qcom/qdsp6/q6usb.c b/sound/soc/qcom/qdsp6/q6usb.c
index 99848a320784..6634e132787e 100644
--- a/sound/soc/qcom/qdsp6/q6usb.c
+++ b/sound/soc/qcom/qdsp6/q6usb.c
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <sound/asound.h>
+#include <sound/jack.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/q6usboffload.h>
@@ -32,6 +33,7 @@ struct q6usb_port_data {
struct auxiliary_device uauxdev;
struct q6afe_usb_cfg usb_cfg;
struct snd_soc_usb *usb;
+ struct snd_soc_jack *hs_jack;
struct q6usb_offload priv;
/* Protects against operations between SOC USB and ASoC */
@@ -144,16 +146,54 @@ static int q6usb_alsa_connection_cb(struct snd_soc_usb *usb,
mutex_lock(&data->mutex);
if (connected) {
+ if (data->hs_jack)
+ snd_jack_report(data->hs_jack->jack, SND_JACK_USB);
+
/* Selects the latest USB headset plugged in for offloading */
list_add_tail(&sdev->list, &data->devices);
} else {
list_del(&sdev->list);
+
+ if (data->hs_jack)
+ snd_jack_report(data->hs_jack->jack, 0);
}
mutex_unlock(&data->mutex);
return 0;
}
+static void q6usb_component_disable_jack(struct q6usb_port_data *data)
+{
+ /* Offload jack has already been disabled */
+ if (!data->hs_jack)
+ return;
+
+ snd_jack_report(data->hs_jack->jack, 0);
+ data->hs_jack = NULL;
+}
+
+static void q6usb_component_enable_jack(struct q6usb_port_data *data,
+ struct snd_soc_jack *jack)
+{
+ snd_jack_report(jack->jack, !list_empty(&data->devices) ? SND_JACK_USB : 0);
+ data->hs_jack = jack;
+}
+
+static int q6usb_component_set_jack(struct snd_soc_component *component,
+ struct snd_soc_jack *jack, void *priv)
+{
+ struct q6usb_port_data *data = dev_get_drvdata(component->dev);
+
+ mutex_lock(&data->mutex);
+ if (jack)
+ q6usb_component_enable_jack(data, jack);
+ else
+ q6usb_component_disable_jack(data);
+ mutex_unlock(&data->mutex);
+
+ return 0;
+}
+
static void q6usb_dai_aux_release(struct device *dev) {}
static int q6usb_dai_add_aux_device(struct q6usb_port_data *data,
@@ -211,6 +251,7 @@ static void q6usb_component_remove(struct snd_soc_component *component)
static const struct snd_soc_component_driver q6usb_dai_component = {
.probe = q6usb_component_probe,
+ .set_jack = q6usb_component_set_jack,
.remove = q6usb_component_remove,
.name = "q6usb-dai-component",
.dapm_widgets = q6usb_dai_widgets,