Skip to contentSkip to conversation

ASoC: sun4i-codec: add headphone dectection for Anbernic RG35XX devices

PATCH Superseded Ryan Walklin 4 participants 11 messages Jan 25, 2025 – Feb 14, 2025

Subsystems (4)

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

v2 cover ASoC: sun4i-codec: add headphone dectection for Anbernic RG35XX devices

Hi All,

V2 of this patch adding support for headphone detection on the Anbernic RG35XX series. No functional changes on this revision, patches refactored to more clearly represent a single change per individual patch, remove vendor prefixing for the device tree binding, improve documentation of the DAPM widget changes and associated UCM, and small whitespace fixes.

Original message below:

This series adds the required device tree bindings to describe GPIOs for jack detection in the sun4i-codec driver, adds support for jack detection to the codec machine driver, and describes the hardware configuration in the RG35XX DTS. The existing speaker amplifier GPIO pin can then be used in concert with jack detection to enable userspace sound servers (via an ALSA UCM configuration) to disable the speaker route when headphones are connected.

Thanks to Chris Morgan for his assistance putting this series together.

Regards,

Ryan

Chris Morgan (4):
ASoC: dt-bindings: sun4i-a10-codec: add hp-det-gpios
ASoC: sun4i-codec: correct dapm widgets and controls for h616
ASoC: sun4i-codec: support hp-det-gpios property
arm64: dts: allwinner: h700: Add hp-det-gpios for Anbernic RG35XX

Ryan Walklin (1):
ASoC: sun4i-codec: change h616 card name

 .../sound/allwinner,sun4i-a10-codec.yaml      |  6 ++
 .../sun50i-h700-anbernic-rg35xx-2024.dts      |  5 +-
 sound/soc/sunxi/sun4i-codec.c                 | 59 ++++++++++++++++++-
 3 files changed, 67 insertions(+), 3 deletions(-)
Signature · 1 line
2.48.1
#1 lore raw

PATCH v2 1/5 ASoC: dt-bindings: sun4i-a10-codec: add hp-det-gpios

From: Chris Morgan <[email protected]>

Devices integrating Allwinner SoCs may use line-out or headphone jacks with jack detection circuits attached to a GPIO. For example, a number of Anbernic devices featuring the H700 SoC use this mechanism to switch between a headphone jack and an internal speaker.

Add extra routing endpoints to support this.

--
Changelog v1..v2:
- Remove vendor prefix from hp-det-gpios
- Amend commit message

---
 .../bindings/sound/allwinner,sun4i-a10-codec.yaml           | 6 ++++++
 1 file changed, 6 insertions(+)
Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml +6 -0
index ccae64ce30719..b4eca702febc7 100644
@@ -102,6 +102,10 @@ properties:
     maxItems: 1
     description: GPIO to enable the external amplifier
 
+  hp-det-gpios:
+    maxItems: 1
+    description: GPIO for headphone/line-out detection
+
 required:
   - "#sound-dai-cells"
   - compatible
@@ -251,8 +255,10 @@ allOf:
         allwinner,audio-routing:
           items:
             enum:
+              - Headphone
               - LINEOUT
               - Line Out
+              - Speaker
 
         dmas:
           items:
Signature · 1 line
2.48.1
maintainer Reviewed-by on v2 1/5
#2 lore raw

Re: [PATCH v2 1/5] ASoC: dt-bindings: sun4i-a10-codec: add hp-det-gpios

Quoted 12 lines · Ryan Walklin

From: Chris Morgan <[email protected]>

Devices integrating Allwinner SoCs may use line-out or headphone jacks with jack detection circuits attached to a GPIO. For example, a number of Anbernic devices featuring the H700 SoC use this mechanism to switch between a headphone jack and an internal speaker.

Add extra routing endpoints to support this.

Quoted 8 lines

--
Changelog v1..v2:
- Remove vendor prefix from hp-det-gpios
- Amend commit message

---
 .../bindings/sound/allwinner,sun4i-a10-codec.yaml           | 6 ++++++
 1 file changed, 6 insertions(+)
#3 lore raw

PATCH v2 2/5 ASoC: sun4i-codec: correct dapm widgets and controls for h616

In reply to Ryan Walklin

From: Chris Morgan <[email protected]>

The previous H616 support patch added a single LINEOUT DAPM pin switch to the card controls. As the codec in this SoC only has a single route, this seemed reasonable at the time, however is redundant given the existing DAPM codec widget definitions controlling the digital and analog sides of the codec.

It is also insufficient to describe the scenario where separate components (muxes, jack detection etc) are used to modify the audio route external to the SoC. For example the Anbernic RG(##)XX series of devices uses a headphone jack detection switch, GPIO-controlled speaker amplifier and a passive external mux chip to route audio.

The LINEOUT route remains defined as the final common endpoint for the codec's output, and is referenced by device trees.

Remove the redundant LINEOUT card control, and add a Speaker pin switch control and Headphone DAPM widget to allow control of the above hardware.

--
Changelog v1..v2:
- Separate DAPM changes into separate patch and add/elaborate rationale.

---
 sound/soc/sunxi/sun4i-codec.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
sound/soc/sunxi/sun4i-codec.c +2 -1
index 886b3fa537d26..f24bbefeb3923 100644
@@ -1916,10 +1916,11 @@ static const struct snd_soc_component_driver sun50i_h616_codec_codec = {
 };
 
 static const struct snd_kcontrol_new sun50i_h616_card_controls[] = {
-	SOC_DAPM_PIN_SWITCH("LINEOUT"),
+	SOC_DAPM_PIN_SWITCH("Speaker"),
 };
 
 static const struct snd_soc_dapm_widget sun50i_h616_codec_card_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone", NULL),
 	SND_SOC_DAPM_LINE("Line Out", NULL),
 	SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event),
 };
Signature · 1 line
2.48.1
#4 lore raw

PATCH v2 3/5 ASoC: sun4i-codec: support hp-det-gpios property

In reply to Ryan Walklin

From: Chris Morgan <[email protected]>

Add support for GPIO headphone detection with the hp-det-gpios property. In order for this to properly disable the path upon removal of headphones, the output must be labelled Headphone which is a common sink in the driver.

Describe a headphone jack and detection GPIO in the driver, check for a corresponding device tree node, and enable jack detection in a new machine init function if described.

--
Changelog v1..v2:
- Whitespace fixes.
- Remove vendor prefix from device tree string.

---
 sound/soc/sunxi/sun4i-codec.c | 53 +++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)
sound/soc/sunxi/sun4i-codec.c +53 -0
index f24bbefeb3923..3701f56c72756 100644
@@ -22,6 +22,7 @@
 #include <linux/gpio/consumer.h>
 
 #include <sound/core.h>
+#include <sound/jack.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
@@ -331,6 +332,7 @@ struct sun4i_codec {
 	struct clk	*clk_module;
 	struct reset_control *rst;
 	struct gpio_desc *gpio_pa;
+	struct gpio_desc *gpio_hp;
 
 	/* ADC_FIFOC register is at different offset on different SoCs */
 	struct regmap_field *reg_adc_fifoc;
@@ -1583,6 +1585,49 @@ static struct snd_soc_dai_driver dummy_cpu_dai = {
 	.ops = &dummy_dai_ops,
 };
 
+static struct snd_soc_jack sun4i_headphone_jack;
+
+static struct snd_soc_jack_pin sun4i_headphone_jack_pins[] = {
+	{ .pin = "Headphone", .mask = SND_JACK_HEADPHONE },
+};
+
+static struct snd_soc_jack_gpio sun4i_headphone_jack_gpio = {
+	.name = "hp-det",
+	.report = SND_JACK_HEADPHONE,
+	.debounce_time = 150,
+};
+
+static int sun4i_codec_machine_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_card *card = rtd->card;
+	struct sun4i_codec *scodec = snd_soc_card_get_drvdata(card);
+	int ret;
+
+	if (scodec->gpio_hp) {
+		ret = snd_soc_card_jack_new_pins(card, "Headphone Jack",
+						 SND_JACK_HEADPHONE,
+						 &sun4i_headphone_jack,
+						 sun4i_headphone_jack_pins,
+						 ARRAY_SIZE(sun4i_headphone_jack_pins));
+		if (ret) {
+			dev_err(rtd->dev,
+				"Headphone jack creation failed: %d\n", ret);
+			return ret;
+		}
+
+		sun4i_headphone_jack_gpio.desc = scodec->gpio_hp;
+		ret = snd_soc_jack_add_gpios(&sun4i_headphone_jack, 1,
+					     &sun4i_headphone_jack_gpio);
+
+		if (ret) {
+			dev_err(rtd->dev, "Headphone GPIO not added: %d\n", ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev,
 							int *num_links)
 {
@@ -1608,6 +1653,7 @@ static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev,
 	link->codecs->name	= dev_name(dev);
 	link->platforms->name	= dev_name(dev);
 	link->dai_fmt		= SND_SOC_DAIFMT_I2S;
+	link->init		= sun4i_codec_machine_init;
 
 	*num_links = 1;
 
@@ -2302,6 +2348,13 @@ static int sun4i_codec_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	scodec->gpio_hp = devm_gpiod_get_optional(&pdev->dev, "hp-det", GPIOD_IN);
+	if (IS_ERR(scodec->gpio_hp)) {
+		ret = PTR_ERR(scodec->gpio_hp);
+		dev_err_probe(&pdev->dev, ret, "Failed to get hp-det gpio\n");
+		return ret;
+	}
+
 	/* reg_field setup */
 	scodec->reg_adc_fifoc = devm_regmap_field_alloc(&pdev->dev,
 							scodec->regmap,
Signature · 1 line
2.48.1
#5 lore raw

PATCH v2 4/5 arm64: dts: allwinner: h700: Add hp-det-gpios for Anbernic RG35XX

In reply to Ryan Walklin

From: Chris Morgan <[email protected]>

Add support for headphone insertion detection via GPIO for the RG35XX series, and add the corresponding routing to the codec node.

--
Changelog v1..v2:
- Remove vendor prefix from GPIO description.
- Whitespace fix

---
 .../boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-2024.dts  | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
arch/arm64/boot/dts/allwinner/sun50i-h700-anbernic-rg35xx-2024.dts +4 -1
index 34c2bb4cc0474..0e3537505d293 100644
@@ -232,8 +232,11 @@ panel_in_rgb: endpoint {
 };
 
 &codec {
-	allwinner,audio-routing = "Line Out", "LINEOUT";
+	/* Both speakers and headphone jack connected to 74HC4052D analog mux */
+	allwinner,audio-routing = "Speaker", "LINEOUT",
+				  "Headphone", "LINEOUT";
 	allwinner,pa-gpios = <&pio 8 5 GPIO_ACTIVE_HIGH>; // PI5
+	hp-det-gpios = <&pio 8 3 GPIO_ACTIVE_HIGH>; // PI3
 	status = "okay";
 };
 
Signature · 1 line
2.48.1
#6 lore raw

PATCH v2 5/5 ASoC: sun4i-codec: change h616 card name

In reply to Ryan Walklin

Adding jack detection requires sound servers to act on the emitted events, which are described by ALSA Use Case Manager configurations in userspace. These configurations include the card name in the file path, so alter the card name for the H616 to remove spaces, making UCM referencing easier. Add a long_name to maintain consistency with the other drivers.

The corresponding ALSA UCM patch is here:
https://github.com/alsa-project/alsa-ucm-conf/pull/491

--
Changelog v1..v2:
- Separate patch for card->long_name
- Note UCM patch link

---
 sound/soc/sunxi/sun4i-codec.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
sound/soc/sunxi/sun4i-codec.c +2 -1
index 3701f56c72756..68e2d82228a0b 100644
@@ -2012,7 +2012,8 @@ static struct snd_soc_card *sun50i_h616_codec_create_card(struct device *dev)
 
 	card->dev		= dev;
 	card->owner		= THIS_MODULE;
-	card->name		= "H616 Audio Codec";
+	card->name		= "h616-audio-codec";
+	card->long_name		= "H616 Audio Codec";
 	card->driver_name	= "sun4i-codec";
 	card->controls		= sun50i_h616_card_controls;
 	card->num_controls	= ARRAY_SIZE(sun50i_h616_card_controls);
Signature · 1 line
2.48.1
#7 lore raw

Re: [PATCH v2 5/5] ASoC: sun4i-codec: change h616 card name

Quoted 29 lines · 在 2025-01-25星期六的 20:00 +1300,Ryan Walklin写道:

Adding jack detection requires sound servers to act on the emitted events, which are described by ALSA Use Case Manager configurations in
userspace. These configurations include the card name in the file path,
so alter the card name for the H616 to remove spaces, making UCM referencing easier. Add a long_name to maintain consistency with the other drivers.

The corresponding ALSA UCM patch is here:
https://github.com/alsa-project/alsa-ucm-conf/pull/491

--
Changelog v1..v2:
- Separate patch for card->long_name
- Note UCM patch link
---
 sound/soc/sunxi/sun4i-codec.c | 3 ++-

 1 file changed, 2 insertions(+), 1 deletion(-)
sound/soc/sunxi/sun4i- renamed from sound/soc/sunxi/sun4i-codec.c +0 -0

codec.c
index 3701f56c72756..68e2d82228a0b 100644

sound/soc/sunxi/sun4i-codec.c +0 -0
@@ -2012,7 +2012,8 @@ static struct snd_soc_card
 *sun50i_h616_codec_create_card(struct device *dev)
Quoted 6 lines


        card->dev               = dev; card->owner             = THIS_MODULE; -       card->name              = "H616 Audio Codec"; +       card->name              = "h616-audio-codec"; +       card->long_name         = "H616 Audio Codec";

I think it's part of the userspace API that should be kept stable.

Quoted 4 lines

        card->driver_name       = "sun4i-codec"; card->controls          = sun50i_h616_card_controls; card->num_controls      = ARRAY_SIZE(sun50i_h616_card_controls);

#8 lore raw

Re: [PATCH v2 5/5] ASoC: sun4i-codec: change h616 card name

Quoted 1 line · Icenowy Zheng

在 2025-01-25星期六的 20:00 +1300,Ryan Walklin写道:

Hi Icenowy, thanks for reviewing!

Quoted 5 lines
Quoted 3 lines

-       card->name              = "H616 Audio Codec"; +       card->name              = "h616-audio-codec"; +       card->long_name         = "H616 Audio Codec";

I think it's part of the userspace API that should be kept stable.

I don't have a strong feeling about this change, but can anyone suggest any other options for how to manage this name being picked up by UCM as a file path? I guess the UCM paths can include spaces, but this is slightly unwieldy and may break if proper escaping is not done.

Would appreciate if any of the ALSA devs could weigh in on best practice here.

Regards,

Ryan

#9 lore raw

Re: [PATCH v2 5/5] ASoC: sun4i-codec: change h616 card name

Quoted 11 lines · Ryan Walklin
Quoted 5 lines · Icenowy Zheng
Quoted 3 lines

-       card->name              = "H616 Audio Codec"; +       card->name              = "h616-audio-codec"; +       card->long_name         = "H616 Audio Codec";

I think it's part of the userspace API that should be kept stable.

I don't have a strong feeling about this change, but can anyone suggest any other options for how to manage this name being picked up by UCM as a file path? I guess the UCM paths can include spaces, but this is slightly unwieldy and may break if proper escaping is not done.

Apologies I have misinterpreted what the user-space code expects, it seems (as per https://github.com/alsa-project/alsa-ucm-conf/blob/master/ucm2/README.md) that the UCM file path is derived from long_name, not name, and name is only used as a fallback if long_name is not provided. Will send a v3 just adding a long_name instead.

Regards,

Ryan

Tested-by on the v2 series
#10 lore raw
In reply to Ryan Walklin

Tested on Allwinner H700 devices.

Quoted 28 lines · Ryan Walklin

Hi All,

V2 of this patch adding support for headphone detection on the Anbernic RG35XX series. No functional changes on this revision, patches refactored to more clearly represent a single change per individual patch, remove vendor prefixing for the device tree binding, improve documentation of the DAPM widget changes and associated UCM, and small whitespace fixes.

Original message below:

This series adds the required device tree bindings to describe GPIOs for jack detection in the sun4i-codec driver, adds support for jack detection to the codec machine driver, and describes the hardware configuration in the RG35XX DTS. The existing speaker amplifier GPIO pin can then be used in concert with jack detection to enable userspace sound servers (via an ALSA UCM configuration) to disable the speaker route when headphones are connected.

Thanks to Chris Morgan for his assistance putting this series together.

Regards,

Ryan

Chris Morgan (4):
ASoC: dt-bindings: sun4i-a10-codec: add hp-det-gpios
ASoC: sun4i-codec: correct dapm widgets and controls for h616
ASoC: sun4i-codec: support hp-det-gpios property
arm64: dts: allwinner: h700: Add hp-det-gpios for Anbernic RG35XX

Ryan Walklin (1):
ASoC: sun4i-codec: change h616 card name

  .../sound/allwinner,sun4i-a10-codec.yaml      |  6 ++
  .../sun50i-h700-anbernic-rg35xx-2024.dts      |  5 +-
  sound/soc/sunxi/sun4i-codec.c                 | 59 ++++++++++++++++++-
  3 files changed, 67 insertions(+), 3 deletions(-)