Skip to content

Commit

Permalink
ASoC: sun4i-codec: add headphone dectection for
Browse files Browse the repository at this point in the history
Merge series from Ryan Walklin <ryan@testtoast.com>:

Hi All,

V3 of this patch adding headphone jack detection support to the Anbernic RGnnXX series of handhelds. V3 corrects my misunderstanding of derivation of ALSA UCM file paths, and adds recieved Reviewed-by and Tested-by tags. Thanks to those that have reviewed and fed back on previous versions.

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 (2):
  ASoC: dt-bindings: sun4i-a10-codec: add hp-det-gpios
  arm64: dts: allwinner: h700: Add hp-det-gpios for Anbernic RG35XX

Ryan Walklin (3):
  ASoC: sun4i-codec: correct dapm widgets and controls for h616
  ASoC: sun4i-codec: support hp-det-gpios property
  ASoC: sun4i-codec: add h616 card long_name

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

--
2.48.1
  • Loading branch information
Mark Brown committed Mar 14, 2025
2 parents e0afd7d + d389719 commit d9a0693
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -251,8 +255,10 @@ allOf:
allwinner,audio-routing:
items:
enum:
- Headphone
- LINEOUT
- Line Out
- Speaker

dmas:
items:
Expand Down
57 changes: 56 additions & 1 deletion sound/soc/sunxi/sun4i-codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand All @@ -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;

Expand Down Expand Up @@ -1916,10 +1962,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),
};
Expand Down Expand Up @@ -1966,6 +2013,7 @@ 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->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);
Expand Down Expand Up @@ -2301,6 +2349,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,
Expand Down

0 comments on commit d9a0693

Please sign in to comment.