155 lines
4.3 KiB
Diff
155 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
|
||
|
|