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

Commit f025d3b9 authored by Jarkko Nikula's avatar Jarkko Nikula Committed by Mark Brown
Browse files

ASoC: jack: Add support for GPIO descriptor defined jack pins



Allow jack GPIO pins be defined also using GPIO descriptor-based interface
in addition to legacy GPIO numbers. This is done by adding two new fields to
struct snd_soc_jack_gpio: idx and gpiod_dev.

Legacy GPIO numbers are used only when GPIO consumer device gpiod_dev is
NULL and otherwise idx is the descriptor index within the GPIO consumer
device.

New function snd_soc_jack_add_gpiods() is added for typical cases where all
GPIO descriptor jack pins belong to same GPIO consumer device. For other
cases the caller must set the gpiod_dev in struct snd_soc_jack_gpio before
calling snd_soc_jack_add_gpios().

Signed-off-by: default avatarJarkko Nikula <jarkko.nikula@linux.intel.com>
Signed-off-by: default avatarMark Brown <broonie@linaro.org>
parent 50dfb69d
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -453,6 +453,9 @@ int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage);
#ifdef CONFIG_GPIOLIB
int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
			struct snd_soc_jack_gpio *gpios);
int snd_soc_jack_add_gpiods(struct device *gpiod_dev,
			    struct snd_soc_jack *jack,
			    int count, struct snd_soc_jack_gpio *gpios);
void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
			struct snd_soc_jack_gpio *gpios);
#else
@@ -462,6 +465,13 @@ static inline int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
	return 0;
}

int snd_soc_jack_add_gpiods(struct device *gpiod_dev,
			    struct snd_soc_jack *jack,
			    int count, struct snd_soc_jack_gpio *gpios)
{
	return 0;
}

static inline void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
					   struct snd_soc_jack_gpio *gpios)
{
@@ -586,7 +596,9 @@ struct snd_soc_jack_zone {
/**
 * struct snd_soc_jack_gpio - Describes a gpio pin for jack detection
 *
 * @gpio:         gpio number
 * @gpio:         legacy gpio number
 * @idx:          gpio descriptor index within the GPIO consumer device
 * @gpiod_dev     GPIO consumer device
 * @name:         gpio name
 * @report:       value to report when jack detected
 * @invert:       report presence in low state
@@ -598,6 +610,8 @@ struct snd_soc_jack_zone {
 */
struct snd_soc_jack_gpio {
	unsigned int gpio;
	unsigned int idx;
	struct device *gpiod_dev;
	const char *name;
	int report;
	int invert;
+57 −16
Original line number Diff line number Diff line
@@ -298,14 +298,30 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
	int i, ret;

	for (i = 0; i < count; i++) {
		if (!gpio_is_valid(gpios[i].gpio)) {
			dev_err(jack->codec->dev, "ASoC: Invalid gpio %d\n",
				gpios[i].gpio);
		if (!gpios[i].name) {
			dev_err(jack->codec->dev,
				"ASoC: No name for gpio at index %d\n", i);
			ret = -EINVAL;
			goto undo;
		}
		if (!gpios[i].name) {
			dev_err(jack->codec->dev, "ASoC: No name for gpio %d\n",

		if (gpios[i].gpiod_dev) {
			/* GPIO descriptor */
			gpios[i].desc = gpiod_get_index(gpios[i].gpiod_dev,
							gpios[i].name,
							gpios[i].idx);
			if (IS_ERR(gpios[i].desc)) {
				ret = PTR_ERR(gpios[i].desc);
				dev_err(gpios[i].gpiod_dev,
					"ASoC: Cannot get gpio at index %d: %d",
					i, ret);
				goto undo;
			}
		} else {
			/* legacy GPIO number */
			if (!gpio_is_valid(gpios[i].gpio)) {
				dev_err(jack->codec->dev,
					"ASoC: Invalid gpio %d\n",
					gpios[i].gpio);
				ret = -EINVAL;
				goto undo;
@@ -316,6 +332,7 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
				goto undo;

			gpios[i].desc = gpio_to_desc(gpios[i].gpio);
		}

		ret = gpiod_direction_input(gpios[i].desc);
		if (ret)
@@ -336,9 +353,9 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
		if (gpios[i].wake) {
			ret = irq_set_irq_wake(gpiod_to_irq(gpios[i].desc), 1);
			if (ret != 0)
				dev_err(jack->codec->dev, "ASoC: "
				  "Failed to mark GPIO %d as wake source: %d\n",
					gpios[i].gpio, ret);
				dev_err(jack->codec->dev,
					"ASoC: Failed to mark GPIO at index %d as wake source: %d\n",
					i, ret);
		}

		/* Expose GPIO value over sysfs for diagnostic purposes */
@@ -360,6 +377,30 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
}
EXPORT_SYMBOL_GPL(snd_soc_jack_add_gpios);

/**
 * snd_soc_jack_add_gpiods - Associate GPIO descriptor pins with an ASoC jack
 *
 * @gpiod_dev: GPIO consumer device
 * @jack:      ASoC jack
 * @count:     number of pins
 * @gpios:     array of gpio pins
 *
 * This function will request gpio, set data direction and request irq
 * for each gpio in the array.
 */
int snd_soc_jack_add_gpiods(struct device *gpiod_dev,
			    struct snd_soc_jack *jack,
			    int count, struct snd_soc_jack_gpio *gpios)
{
	int i;

	for (i = 0; i < count; i++)
		gpios[i].gpiod_dev = gpiod_dev;

	return snd_soc_jack_add_gpios(jack, count, gpios);
}
EXPORT_SYMBOL_GPL(snd_soc_jack_add_gpiods);

/**
 * snd_soc_jack_free_gpios - Release GPIO pins' resources of an ASoC jack
 *