diff options
| author | Wesley Cheng <quic_wcheng@quicinc.com> | 2025-04-09 12:47:58 -0700 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2025-04-11 13:02:32 +0200 |
| commit | 1b8d0d87b934f002a06a8ec2abfe907bd12e8cd4 (patch) | |
| tree | 3631dc626fffedea0b54e60323cdfb3536246405 /sound/soc/qcom/qdsp6 | |
| parent | 72b0b8b2998043c50b191d9668c7a828ca0d5c70 (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.c | 41 |
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, |
