diff mbox series

[v4,29/32] sound: soc: qcom: q6usb: Add headphone jack for offload connection status

Message ID 20230725023416.11205-30-quic_wcheng@quicinc.com (mailing list archive)
State Superseded
Headers show
Series Introduce QC USB SND audio offloading support | expand

Commit Message

Wesley Cheng July 25, 2023, 2:34 a.m. UTC
The headphone jack framework has a well defined intrastructure 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>
---
 sound/soc/qcom/qdsp6/q6usb.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

Comments

Pierre-Louis Bossart July 25, 2023, 9:10 a.m. UTC | #1
On 7/25/23 04:34, Wesley Cheng wrote:
> The headphone jack framework has a well defined intrastructure for

infrastructure

> 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.

What if you connect a set of USB speakers? Would they show as a
headphone/headset?

> Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com>
> ---
>  sound/soc/qcom/qdsp6/q6usb.c | 17 +++++++++++++++--
>  1 file changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/sound/soc/qcom/qdsp6/q6usb.c b/sound/soc/qcom/qdsp6/q6usb.c
> index e4ccb9d912b0..860dff8c1438 100644
> --- a/sound/soc/qcom/qdsp6/q6usb.c
> +++ b/sound/soc/qcom/qdsp6/q6usb.c
> @@ -20,6 +20,7 @@
>  #include <sound/pcm_params.h>
>  #include <sound/asound.h>
>  #include <sound/q6usboffload.h>
> +#include <sound/jack.h>
>  
>  #include "q6dsp-lpass-ports.h"
>  #include "q6afe.h"
> @@ -37,6 +38,7 @@ struct q6usb_status {
>  struct q6usb_port_data {
>  	struct q6afe_usb_cfg usb_cfg;
>  	struct snd_soc_usb *usb;
> +	struct snd_soc_jack hs_jack;
>  	struct q6usb_offload priv;
>  	struct mutex mutex;
>  	unsigned long available_card_slot;
> @@ -279,6 +281,7 @@ static const struct snd_kcontrol_new q6usb_offload_control = {
>  /* Build a mixer control for a UAC connector control (jack-detect) */
>  static void q6usb_connector_control_init(struct snd_soc_component *component)
>  {
> +	struct q6usb_port_data *data = dev_get_drvdata(component->dev);
>  	int ret;
>  
>  	ret = snd_ctl_add(component->card->snd_card,
> @@ -290,6 +293,11 @@ static void q6usb_connector_control_init(struct snd_soc_component *component)
>  				snd_ctl_new1(&q6usb_offload_dev_ctrl, component));
>  	if (ret < 0)
>  		return;
> +
> +	ret = snd_soc_card_jack_new(component->card, "USB offload",
> +					SND_JACK_HEADSET, &data->hs_jack);

not all USB devices are headsets...

> +	if (ret)
> +		return;
>  }
>  
>  static int q6usb_audio_ports_of_xlate_dai_name(struct snd_soc_component *component,
> @@ -322,7 +330,10 @@ static int q6usb_alsa_connection_cb(struct snd_soc_usb *usb, int card_idx,
>  
>  	mutex_lock(&data->mutex);
>  	if (connected) {
> -		snd_soc_dapm_enable_pin(dapm, "USB_RX_BE");
> +		if (!data->available_card_slot) {
> +			snd_soc_dapm_enable_pin(dapm, "USB_RX_BE");
> +			snd_jack_report(data->hs_jack.jack, 1);
> +		}
>  		/*
>  		 * Update the latest USB headset plugged in, if session is
>  		 * idle.
> @@ -338,8 +349,10 @@ static int q6usb_alsa_connection_cb(struct snd_soc_usb *usb, int card_idx,
>  		clear_bit(card_idx, &data->available_card_slot);
>  		data->status[card_idx].num_pcm = 0;
>  		data->status[card_idx].chip_index = 0;
> -		if (!data->available_card_slot)
> +		if (!data->available_card_slot) {
>  			snd_soc_dapm_disable_pin(dapm, "USB_RX_BE");
> +			snd_jack_report(data->hs_jack.jack, 0);
> +		}
>  	}
>  	snd_soc_dapm_sync(dapm);
>  	mutex_unlock(&data->mutex);
Wesley Cheng Aug. 16, 2023, 1:11 a.m. UTC | #2
Hi Pierre,

On 7/25/2023 2:10 AM, Pierre-Louis Bossart wrote:
> 
> 
> On 7/25/23 04:34, Wesley Cheng wrote:
>> The headphone jack framework has a well defined intrastructure for
> 
> infrastructure
> 
>> 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.
> 
> What if you connect a set of USB speakers? Would they show as a
> headphone/headset?
> 

For now, let me modify the patch to send a HEADPHONE event.  We don't 
support the capture/record path as of now, so it doesn't make sense to 
generate a HEADSET event (which exposes both MIC and HEADPHONE).

When you plug in any USB audio device we'd generate this snd jack event. 
  Main purpose was to notify that the offload path is potentially available.

Thanks
Wesley Cheng

>> Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com>
>> ---
>>   sound/soc/qcom/qdsp6/q6usb.c | 17 +++++++++++++++--
>>   1 file changed, 15 insertions(+), 2 deletions(-)
>>
>> diff --git a/sound/soc/qcom/qdsp6/q6usb.c b/sound/soc/qcom/qdsp6/q6usb.c
>> index e4ccb9d912b0..860dff8c1438 100644
>> --- a/sound/soc/qcom/qdsp6/q6usb.c
>> +++ b/sound/soc/qcom/qdsp6/q6usb.c
>> @@ -20,6 +20,7 @@
>>   #include <sound/pcm_params.h>
>>   #include <sound/asound.h>
>>   #include <sound/q6usboffload.h>
>> +#include <sound/jack.h>
>>   
>>   #include "q6dsp-lpass-ports.h"
>>   #include "q6afe.h"
>> @@ -37,6 +38,7 @@ struct q6usb_status {
>>   struct q6usb_port_data {
>>   	struct q6afe_usb_cfg usb_cfg;
>>   	struct snd_soc_usb *usb;
>> +	struct snd_soc_jack hs_jack;
>>   	struct q6usb_offload priv;
>>   	struct mutex mutex;
>>   	unsigned long available_card_slot;
>> @@ -279,6 +281,7 @@ static const struct snd_kcontrol_new q6usb_offload_control = {
>>   /* Build a mixer control for a UAC connector control (jack-detect) */
>>   static void q6usb_connector_control_init(struct snd_soc_component *component)
>>   {
>> +	struct q6usb_port_data *data = dev_get_drvdata(component->dev);
>>   	int ret;
>>   
>>   	ret = snd_ctl_add(component->card->snd_card,
>> @@ -290,6 +293,11 @@ static void q6usb_connector_control_init(struct snd_soc_component *component)
>>   				snd_ctl_new1(&q6usb_offload_dev_ctrl, component));
>>   	if (ret < 0)
>>   		return;
>> +
>> +	ret = snd_soc_card_jack_new(component->card, "USB offload",
>> +					SND_JACK_HEADSET, &data->hs_jack);
> 
> not all USB devices are headsets...
> 
>> +	if (ret)
>> +		return;
>>   }
>>   
>>   static int q6usb_audio_ports_of_xlate_dai_name(struct snd_soc_component *component,
>> @@ -322,7 +330,10 @@ static int q6usb_alsa_connection_cb(struct snd_soc_usb *usb, int card_idx,
>>   
>>   	mutex_lock(&data->mutex);
>>   	if (connected) {
>> -		snd_soc_dapm_enable_pin(dapm, "USB_RX_BE");
>> +		if (!data->available_card_slot) {
>> +			snd_soc_dapm_enable_pin(dapm, "USB_RX_BE");
>> +			snd_jack_report(data->hs_jack.jack, 1);
>> +		}
>>   		/*
>>   		 * Update the latest USB headset plugged in, if session is
>>   		 * idle.
>> @@ -338,8 +349,10 @@ static int q6usb_alsa_connection_cb(struct snd_soc_usb *usb, int card_idx,
>>   		clear_bit(card_idx, &data->available_card_slot);
>>   		data->status[card_idx].num_pcm = 0;
>>   		data->status[card_idx].chip_index = 0;
>> -		if (!data->available_card_slot)
>> +		if (!data->available_card_slot) {
>>   			snd_soc_dapm_disable_pin(dapm, "USB_RX_BE");
>> +			snd_jack_report(data->hs_jack.jack, 0);
>> +		}
>>   	}
>>   	snd_soc_dapm_sync(dapm);
>>   	mutex_unlock(&data->mutex);
diff mbox series

Patch

diff --git a/sound/soc/qcom/qdsp6/q6usb.c b/sound/soc/qcom/qdsp6/q6usb.c
index e4ccb9d912b0..860dff8c1438 100644
--- a/sound/soc/qcom/qdsp6/q6usb.c
+++ b/sound/soc/qcom/qdsp6/q6usb.c
@@ -20,6 +20,7 @@ 
 #include <sound/pcm_params.h>
 #include <sound/asound.h>
 #include <sound/q6usboffload.h>
+#include <sound/jack.h>
 
 #include "q6dsp-lpass-ports.h"
 #include "q6afe.h"
@@ -37,6 +38,7 @@  struct q6usb_status {
 struct q6usb_port_data {
 	struct q6afe_usb_cfg usb_cfg;
 	struct snd_soc_usb *usb;
+	struct snd_soc_jack hs_jack;
 	struct q6usb_offload priv;
 	struct mutex mutex;
 	unsigned long available_card_slot;
@@ -279,6 +281,7 @@  static const struct snd_kcontrol_new q6usb_offload_control = {
 /* Build a mixer control for a UAC connector control (jack-detect) */
 static void q6usb_connector_control_init(struct snd_soc_component *component)
 {
+	struct q6usb_port_data *data = dev_get_drvdata(component->dev);
 	int ret;
 
 	ret = snd_ctl_add(component->card->snd_card,
@@ -290,6 +293,11 @@  static void q6usb_connector_control_init(struct snd_soc_component *component)
 				snd_ctl_new1(&q6usb_offload_dev_ctrl, component));
 	if (ret < 0)
 		return;
+
+	ret = snd_soc_card_jack_new(component->card, "USB offload",
+					SND_JACK_HEADSET, &data->hs_jack);
+	if (ret)
+		return;
 }
 
 static int q6usb_audio_ports_of_xlate_dai_name(struct snd_soc_component *component,
@@ -322,7 +330,10 @@  static int q6usb_alsa_connection_cb(struct snd_soc_usb *usb, int card_idx,
 
 	mutex_lock(&data->mutex);
 	if (connected) {
-		snd_soc_dapm_enable_pin(dapm, "USB_RX_BE");
+		if (!data->available_card_slot) {
+			snd_soc_dapm_enable_pin(dapm, "USB_RX_BE");
+			snd_jack_report(data->hs_jack.jack, 1);
+		}
 		/*
 		 * Update the latest USB headset plugged in, if session is
 		 * idle.
@@ -338,8 +349,10 @@  static int q6usb_alsa_connection_cb(struct snd_soc_usb *usb, int card_idx,
 		clear_bit(card_idx, &data->available_card_slot);
 		data->status[card_idx].num_pcm = 0;
 		data->status[card_idx].chip_index = 0;
-		if (!data->available_card_slot)
+		if (!data->available_card_slot) {
 			snd_soc_dapm_disable_pin(dapm, "USB_RX_BE");
+			snd_jack_report(data->hs_jack.jack, 0);
+		}
 	}
 	snd_soc_dapm_sync(dapm);
 	mutex_unlock(&data->mutex);