pmaports/device/testing/linux-postmarketos-exynos5/0025-WIP-ASoC-samsung-snow-add-jack-detection-support.patch

154 lines
4.3 KiB
Diff

From dcde1b82bbf5bb4b4f58beb1dfa593d4d8e1501e Mon Sep 17 00:00:00 2001
From: Anton Bambura <jenneron@protonmail.com>
Date: Sat, 5 Feb 2022 03:19:07 +0200
Subject: [PATCH 1/3] WIP: ASoC: samsung: snow: add jack detection support
Add jack detection support with two GPIOs:
- samsung,hp-det;
- samsung,mic-det.
This change works (alsa sends events, pulseaudio switches devices), but
there are such messages in kmsg on each plug/unplug:
[ 85.673023] snow-audio sound: ASoC: DAPM unknown pin Headphone
[ 86.005010] snow-audio sound: ASoC: DAPM unknown pin Mic Jack
Signed-off-by: Anton Bambura <jenneron@protonmail.com>
---
sound/soc/samsung/snow.c | 86 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c
index 6da674e90..bd534c56f 100644
--- a/sound/soc/samsung/snow.c
+++ b/sound/soc/samsung/snow.c
@@ -3,10 +3,12 @@
// ASoC machine driver for Snow boards
#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <sound/jack.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@@ -22,6 +24,32 @@ SND_SOC_DAILINK_DEFS(links,
struct snow_priv {
struct snd_soc_dai_link dai_link;
struct clk *clk_i2s_bus;
+ struct gpio_desc *gpiod_hp_det;
+ struct gpio_desc *gpiod_mic_det;
+};
+
+static struct snd_soc_jack snow_hp_jack;
+
+static struct snd_soc_jack_pin snow_hp_jack_pins[] = {
+ { .pin = "Headphone", .mask = SND_JACK_HEADPHONE },
+};
+
+static struct snd_soc_jack_gpio snow_hp_jack_gpio = {
+ .name = "Headphones detection",
+ .report = SND_JACK_HEADPHONE,
+ .debounce_time = 150,
+};
+
+static struct snd_soc_jack snow_mic_jack;
+
+static struct snd_soc_jack_pin snow_mic_jack_pins[] = {
+ { .pin = "Mic Jack", .mask = SND_JACK_MICROPHONE },
+};
+
+static struct snd_soc_jack_gpio snow_mic_jack_gpio = {
+ .name = "Microphone detection",
+ .report = SND_JACK_MICROPHONE,
+ .debounce_time = 150,
};
static int snow_card_hw_params(struct snd_pcm_substream *substream,
@@ -105,9 +133,56 @@ static int snow_late_probe(struct snd_soc_card *card)
{
struct snd_soc_pcm_runtime *rtd;
struct snd_soc_dai *codec_dai;
+ struct snow_priv *priv = snd_soc_card_get_drvdata(card);
+ const char *jack_name;
+ int err;
rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
+ if (priv->gpiod_hp_det) {
+ jack_name = "Headphones";
+
+ err = snd_soc_card_jack_new(card, jack_name,
+ SND_JACK_HEADPHONE,
+ &snow_hp_jack,
+ snow_hp_jack_pins,
+ ARRAY_SIZE(snow_hp_jack_pins));
+ if (err) {
+ dev_err(rtd->dev,
+ "Headphones Jack creation failed: %d\n", err);
+ return err;
+ }
+
+ snow_hp_jack_gpio.desc = priv->gpiod_hp_det;
+
+ err = snd_soc_jack_add_gpios(&snow_hp_jack, 1,
+ &snow_hp_jack_gpio);
+ if (err)
+ dev_err(rtd->dev, "Headphones GPIOs not added: %d\n", err);
+ }
+
+ if (priv->gpiod_mic_det) {
+ jack_name = "Microphone";
+
+ err = snd_soc_card_jack_new(card, jack_name,
+ SND_JACK_MICROPHONE,
+ &snow_mic_jack,
+ snow_mic_jack_pins,
+ ARRAY_SIZE(snow_mic_jack_pins));
+ if (err) {
+ dev_err(rtd->dev,
+ "Microphone Jack creation failed: %d\n", err);
+ return err;
+ }
+
+ snow_mic_jack_gpio.desc = priv->gpiod_mic_det;
+
+ err = snd_soc_jack_add_gpios(&snow_mic_jack, 1,
+ &snow_mic_jack_gpio);
+ if (err)
+ dev_err(rtd->dev, "Microphone GPIOs not added: %d\n", err);
+ }
+
/* In the multi-codec case codec_dais 0 is MAX98095 and 1 is HDMI. */
codec_dai = asoc_rtd_to_codec(rtd, 0);
@@ -129,6 +204,7 @@ static int snow_probe(struct platform_device *pdev)
struct device_node *cpu, *codec;
struct snd_soc_dai_link *link;
struct snow_priv *priv;
+ struct gpio_desc *gpiod;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -137,6 +213,16 @@ static int snow_probe(struct platform_device *pdev)
link = &priv->dai_link;
+ gpiod = devm_gpiod_get_optional(dev, "samsung,hp-det", GPIOD_IN);
+ priv->gpiod_hp_det = gpiod;
+ if (IS_ERR(gpiod))
+ return PTR_ERR(gpiod);
+
+ gpiod = devm_gpiod_get_optional(dev, "samsung,mic-det", GPIOD_IN);
+ priv->gpiod_mic_det = gpiod;
+ if (IS_ERR(gpiod))
+ return PTR_ERR(gpiod);
+
link->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS;
--
2.34.1