Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3fe24032 authored by Dylan Reid's avatar Dylan Reid Committed by Mark Brown
Browse files

ASoC: simple-card: Add mic and hp detect gpios.



Allow Headphone and Microphone jack detect gpios to be specified in
device tree.  This will allow a few systems including rk3288_max98090
to use simple-card instead of having their own board file.

Signed-off-by: default avatarDylan Reid <dgreid@chromium.org>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 04a0b8ef
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -17,6 +17,10 @@ Optional properties:
					  source.
- simple-audio-card,mclk-fs             : Multiplication factor between stream rate and codec
  					  mclk.
- simple-audio-card,hp_det_gpio		: Reference to GPIO that signals when
					  headphones are attached.
- simple-audio-card,mic_det_gpio	: Reference to GPIO that signals when
					  a microphone is attached.

Optional subnodes:

+73 −0
Original line number Diff line number Diff line
@@ -10,10 +10,13 @@
 */
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/string.h>
#include <sound/jack.h>
#include <sound/simple_card.h>
#include <sound/soc-dai.h>
#include <sound/soc.h>
@@ -25,6 +28,8 @@ struct simple_card_data {
		struct asoc_simple_dai codec_dai;
	} *dai_props;
	unsigned int mclk_fs;
	int gpio_hp_det;
	int gpio_mic_det;
	struct snd_soc_dai_link dai_link[];	/* dynamically allocated */
};

@@ -54,6 +59,32 @@ static struct snd_soc_ops asoc_simple_card_ops = {
	.hw_params = asoc_simple_card_hw_params,
};

static struct snd_soc_jack simple_card_hp_jack;
static struct snd_soc_jack_pin simple_card_hp_jack_pins[] = {
	{
		.pin = "Headphones",
		.mask = SND_JACK_HEADPHONE,
	},
};
static struct snd_soc_jack_gpio simple_card_hp_jack_gpio = {
	.name = "Headphone detection",
	.report = SND_JACK_HEADPHONE,
	.debounce_time = 150,
};

static struct snd_soc_jack simple_card_mic_jack;
static struct snd_soc_jack_pin simple_card_mic_jack_pins[] = {
	{
		.pin = "Mic Jack",
		.mask = SND_JACK_MICROPHONE,
	},
};
static struct snd_soc_jack_gpio simple_card_mic_jack_gpio = {
	.name = "Mic detection",
	.report = SND_JACK_MICROPHONE,
	.debounce_time = 150,
};

static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai,
				       struct asoc_simple_dai *set)
{
@@ -109,6 +140,28 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
	if (ret < 0)
		return ret;

	if (gpio_is_valid(priv->gpio_hp_det)) {
		snd_soc_jack_new(codec->codec, "Headphones", SND_JACK_HEADPHONE,
				 &simple_card_hp_jack);
		snd_soc_jack_add_pins(&simple_card_hp_jack,
				      ARRAY_SIZE(simple_card_hp_jack_pins),
				      simple_card_hp_jack_pins);

		simple_card_hp_jack_gpio.gpio = priv->gpio_hp_det;
		snd_soc_jack_add_gpios(&simple_card_hp_jack, 1,
				       &simple_card_hp_jack_gpio);
	}

	if (gpio_is_valid(priv->gpio_mic_det)) {
		snd_soc_jack_new(codec->codec, "Mic Jack", SND_JACK_MICROPHONE,
				 &simple_card_mic_jack);
		snd_soc_jack_add_pins(&simple_card_mic_jack,
				      ARRAY_SIZE(simple_card_mic_jack_pins),
				      simple_card_mic_jack_pins);
		simple_card_mic_jack_gpio.gpio = priv->gpio_mic_det;
		snd_soc_jack_add_gpios(&simple_card_mic_jack, 1,
				       &simple_card_mic_jack_gpio);
	}
	return 0;
}

@@ -383,6 +436,16 @@ static int asoc_simple_card_parse_of(struct device_node *node,
			return ret;
	}

	priv->gpio_hp_det = of_get_named_gpio(node,
				"simple-audio-card,hp-det-gpio", 0);
	if (priv->gpio_hp_det == -EPROBE_DEFER)
		return -EPROBE_DEFER;

	priv->gpio_mic_det = of_get_named_gpio(node,
				"simple-audio-card,mic-det-gpio", 0);
	if (priv->gpio_mic_det == -EPROBE_DEFER)
		return -EPROBE_DEFER;

	if (!priv->snd_card.name)
		priv->snd_card.name = priv->snd_card.dai_link->name;

@@ -502,6 +565,16 @@ static int asoc_simple_card_probe(struct platform_device *pdev)

static int asoc_simple_card_remove(struct platform_device *pdev)
{
	struct snd_soc_card *card = platform_get_drvdata(pdev);
	struct simple_card_data *priv = snd_soc_card_get_drvdata(card);

	if (gpio_is_valid(priv->gpio_hp_det))
		snd_soc_jack_free_gpios(&simple_card_hp_jack, 1,
					&simple_card_hp_jack_gpio);
	if (gpio_is_valid(priv->gpio_mic_det))
		snd_soc_jack_free_gpios(&simple_card_mic_jack, 1,
					&simple_card_mic_jack_gpio);

	return asoc_simple_card_unref(pdev);
}