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: Jarkko Nikula <jarkko.nikula@linux.intel.com> Signed-off-by: Mark Brown <broonie@linaro.org>
This commit is contained in:
Родитель
50dfb69d1b
Коммит
f025d3b9c6
|
@ -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;
|
||||
|
|
|
@ -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 @@ undo:
|
|||
}
|
||||
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
|
||||
*
|
||||
|
|
Загрузка…
Ссылка в новой задаче