From f025d3b9c64e1f7feb75a559d4a12f5f8c6a4a25 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 26 May 2014 14:34:37 +0300 Subject: 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 Signed-off-by: Mark Brown --- sound/soc/soc-jack.c | 73 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 16 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 7203842fea66..d0d98810af91 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -298,24 +298,41 @@ 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); - ret = -EINVAL; - goto undo; - } if (!gpios[i].name) { - dev_err(jack->codec->dev, "ASoC: No name for gpio %d\n", - gpios[i].gpio); + dev_err(jack->codec->dev, + "ASoC: No name for gpio at index %d\n", i); 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); + 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; + } + + 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); 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 * -- cgit v1.2.3