From dcde1b82bbf5bb4b4f58beb1dfa593d4d8e1501e Mon Sep 17 00:00:00 2001 From: Anton Bambura 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 --- 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 +#include #include #include #include #include +#include #include #include @@ -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