From a60b595873e36af9ff321808f409051906a7c6d5 Mon Sep 17 00:00:00 2001 From: Anton Bambura Date: Sat, 5 Feb 2022 03:19:07 +0200 Subject: [PATCH 10/33] ASoC: samsung: snow: add jack detection Add jack detection support with two GPIOs: - samsung,hp-det; - samsung,mic-det. Signed-off-by: Anton Bambura --- sound/soc/samsung/snow.c | 94 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c index 02372109c251..e0232dd2afdb 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,37 @@ 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 Jack", .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 const struct snd_soc_dapm_widget snow_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Mic Jack", NULL), }; static int snow_card_hw_params(struct snd_pcm_substream *substream, @@ -105,9 +138,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 +209,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 +218,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; @@ -154,6 +245,9 @@ static int snow_probe(struct platform_device *pdev) card->num_links = 1; card->dev = dev; + card->dapm_widgets = snow_dapm_widgets; + card->num_dapm_widgets = ARRAY_SIZE(snow_dapm_widgets); + /* Try new DT bindings with HDMI support first. */ cpu = of_get_child_by_name(dev->of_node, "cpu"); -- 2.38.0