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

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
...@@ -453,6 +453,9 @@ int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage); ...@@ -453,6 +453,9 @@ int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage);
#ifdef CONFIG_GPIOLIB #ifdef CONFIG_GPIOLIB
int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
struct snd_soc_jack_gpio *gpios); 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, void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
struct snd_soc_jack_gpio *gpios); struct snd_soc_jack_gpio *gpios);
#else #else
...@@ -462,6 +465,13 @@ static inline int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, ...@@ -462,6 +465,13 @@ static inline int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
return 0; 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, static inline void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
struct snd_soc_jack_gpio *gpios) struct snd_soc_jack_gpio *gpios)
{ {
...@@ -586,7 +596,9 @@ struct snd_soc_jack_zone { ...@@ -586,7 +596,9 @@ struct snd_soc_jack_zone {
/** /**
* struct snd_soc_jack_gpio - Describes a gpio pin for jack detection * 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 * @name: gpio name
* @report: value to report when jack detected * @report: value to report when jack detected
* @invert: report presence in low state * @invert: report presence in low state
...@@ -598,6 +610,8 @@ struct snd_soc_jack_zone { ...@@ -598,6 +610,8 @@ struct snd_soc_jack_zone {
*/ */
struct snd_soc_jack_gpio { struct snd_soc_jack_gpio {
unsigned int gpio; unsigned int gpio;
unsigned int idx;
struct device *gpiod_dev;
const char *name; const char *name;
int report; int report;
int invert; int invert;
......
...@@ -298,24 +298,41 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, ...@@ -298,24 +298,41 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
int i, ret; int i, ret;
for (i = 0; i < count; i++) { 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);
ret = -EINVAL;
goto undo;
}
if (!gpios[i].name) { if (!gpios[i].name) {
dev_err(jack->codec->dev, "ASoC: No name for gpio %d\n", dev_err(jack->codec->dev,
gpios[i].gpio); "ASoC: No name for gpio at index %d\n", i);
ret = -EINVAL; ret = -EINVAL;
goto undo; goto undo;
} }
ret = gpio_request(gpios[i].gpio, gpios[i].name); if (gpios[i].gpiod_dev) {
if (ret) /* GPIO descriptor */
goto undo; gpios[i].desc = gpiod_get_index(gpios[i].gpiod_dev,
gpios[i].name,
gpios[i].desc = gpio_to_desc(gpios[i].gpio); 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;
}
ret = gpio_request(gpios[i].gpio, gpios[i].name);
if (ret)
goto undo;
gpios[i].desc = gpio_to_desc(gpios[i].gpio);
}
ret = gpiod_direction_input(gpios[i].desc); ret = gpiod_direction_input(gpios[i].desc);
if (ret) if (ret)
...@@ -336,9 +353,9 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, ...@@ -336,9 +353,9 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
if (gpios[i].wake) { if (gpios[i].wake) {
ret = irq_set_irq_wake(gpiod_to_irq(gpios[i].desc), 1); ret = irq_set_irq_wake(gpiod_to_irq(gpios[i].desc), 1);
if (ret != 0) if (ret != 0)
dev_err(jack->codec->dev, "ASoC: " dev_err(jack->codec->dev,
"Failed to mark GPIO %d as wake source: %d\n", "ASoC: Failed to mark GPIO at index %d as wake source: %d\n",
gpios[i].gpio, ret); i, ret);
} }
/* Expose GPIO value over sysfs for diagnostic purposes */ /* 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, ...@@ -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); 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 * snd_soc_jack_free_gpios - Release GPIO pins' resources of an ASoC jack
* *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment