From: Robert Jarzmik <robert.jarzmik@free.fr>
To: Liam Girdwood <lgirdwood@gmail.com>,
Mark Brown <broonie@kernel.org>, Jaroslav Kysela <perex@perex.cz>,
Takashi Iwai <tiwai@suse.com>
Cc: patches@opensource.wolfsonmicro.com, alsa-devel@alsa-project.org,
linux-kernel@vger.kernel.org,
Robert Jarzmik <robert.jarzmik@free.fr>
Subject: [PATCH] ASoC: wm9713: add gpio chip
Date: Wed, 4 Nov 2015 18:12:44 +0100 [thread overview]
Message-ID: <1446657164-25012-1-git-send-email-robert.jarzmik@free.fr> (raw)
The Wolfson WM9713 provides 8 GPIOs. If the gpiolib is compiled in the
kernel, declare a gpio chip.
Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
---
sound/soc/codecs/wm9713.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++
sound/soc/codecs/wm9713.h | 1 +
2 files changed, 124 insertions(+)
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 79e143625ac3..904fe4fc5bf1 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -19,6 +19,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/device.h>
+#include <linux/gpio/driver.h>
#include <linux/regmap.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -33,11 +34,21 @@
#define WM9713_VENDOR_ID 0x574d4c13
#define WM9713_VENDOR_ID_MASK 0xffffffff
+#define AC97_GPIO_PUSH_PULL 0x58
+
+struct wm9713_gpio_priv {
+#ifdef CONFIG_GPIOLIB
+ struct gpio_chip gpio_chip;
+#endif
+ struct snd_soc_codec *codec;
+};
+
struct wm9713_priv {
struct snd_ac97 *ac97;
u32 pll_in; /* PLL input frequency */
unsigned int hp_mixer[2];
struct mutex lock;
+ struct wm9713_gpio_priv *gpio_priv;
};
#define HPL_MIXER 0
@@ -1202,10 +1213,116 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec)
return ret;
}
+#ifdef CONFIG_GPIOLIB
+static inline struct snd_soc_codec *gpio_to_codec(struct gpio_chip *chip)
+{
+ struct wm9713_gpio_priv *gpio_priv =
+ container_of(chip, struct wm9713_gpio_priv, gpio_chip);
+
+ return gpio_priv->codec;
+}
+
+static int wm9713_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ if (offset >= WM9713_NUM_GPIOS)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int wm9713_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+ struct snd_soc_codec *codec = gpio_to_codec(chip);
+
+ return snd_soc_update_bits(codec, AC97_GPIO_CFG,
+ 1 << (offset + 1), 1 << (offset + 1));
+}
+
+static int wm9713_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct snd_soc_codec *codec = gpio_to_codec(chip);
+ int ret;
+
+ ret = snd_soc_read(codec, AC97_GPIO_STATUS);
+
+ return ret < 0 ? ret : ret & (1 << (offset + 1));
+}
+
+static void wm9713_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct snd_soc_codec *codec = gpio_to_codec(chip);
+
+ snd_soc_update_bits(codec, AC97_GPIO_PUSH_PULL,
+ 1 << offset | (1 << (offset + 8)),
+ 1 << (offset + 8 * !!value));
+}
+
+static int wm9713_gpio_direction_out(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct snd_soc_codec *codec = gpio_to_codec(chip);
+
+ wm9713_gpio_set(chip, offset, value);
+
+ return snd_soc_update_bits(codec, AC97_GPIO_CFG, 1 << (offset + 1), 0);
+}
+
+static struct gpio_chip wm9713_gpio_chip = {
+ .label = "wm9713",
+ .owner = THIS_MODULE,
+ .request = wm9713_gpio_request,
+ .direction_input = wm9713_gpio_direction_in,
+ .get = wm9713_gpio_get,
+ .direction_output = wm9713_gpio_direction_out,
+ .set = wm9713_gpio_set,
+ .can_sleep = 1,
+};
+
+static int wm9713_init_gpio(struct snd_soc_codec *codec)
+{
+ struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
+ struct wm9713_gpio_priv *gpio_priv;
+ int ret;
+
+ gpio_priv = devm_kzalloc(codec->dev, sizeof(*wm9713->gpio_priv),
+ GFP_KERNEL);
+ if (!gpio_priv)
+ return -ENOMEM;
+ wm9713->gpio_priv = gpio_priv;
+ gpio_priv->codec = codec;
+ gpio_priv->gpio_chip = wm9713_gpio_chip;
+ gpio_priv->gpio_chip.ngpio = WM9713_NUM_GPIOS;
+ gpio_priv->gpio_chip.dev = codec->dev;
+ gpio_priv->gpio_chip.base = -1;
+
+ ret = gpiochip_add(&gpio_priv->gpio_chip);
+ if (ret != 0)
+ dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret);
+ return ret;
+}
+
+static void wm9713_free_gpio(struct snd_soc_codec *codec)
+{
+ struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
+
+ gpiochip_remove(&wm9713->gpio_priv->gpio_chip);
+}
+#else
+static int wm9713_init_gpio(struct snd_soc_codec *codec)
+{
+ return 0;
+}
+
+static void wm9713_free_gpio(struct snd_soc_codec *codec)
+{
+}
+#endif
+
static int wm9713_soc_probe(struct snd_soc_codec *codec)
{
struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
struct regmap *regmap;
+ int ret;
wm9713->ac97 = snd_soc_new_ac97_codec(codec, WM9713_VENDOR_ID,
WM9713_VENDOR_ID_MASK);
@@ -1223,6 +1340,11 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec)
/* unmute the adc - move to kcontrol */
snd_soc_update_bits(codec, AC97_CD, 0x7fff, 0x0000);
+ ret = wm9713_init_gpio(codec);
+ if (ret) {
+ snd_soc_free_ac97_codec(wm9713->ac97);
+ return ret;
+ }
return 0;
}
@@ -1230,6 +1352,7 @@ static int wm9713_soc_remove(struct snd_soc_codec *codec)
{
struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
+ wm9713_free_gpio(codec);
snd_soc_codec_exit_regmap(codec);
snd_soc_free_ac97_codec(wm9713->ac97);
return 0;
diff --git a/sound/soc/codecs/wm9713.h b/sound/soc/codecs/wm9713.h
index 53df11b1f727..d72f96e653d1 100644
--- a/sound/soc/codecs/wm9713.h
+++ b/sound/soc/codecs/wm9713.h
@@ -45,4 +45,5 @@
#define WM9713_DAI_AC97_AUX 1
#define WM9713_DAI_PCM_VOICE 2
+#define WM9713_NUM_GPIOS 8
#endif
--
2.1.4
next reply other threads:[~2015-11-04 17:19 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-11-04 17:12 Robert Jarzmik [this message]
2015-11-04 18:33 ` [PATCH] ASoC: wm9713: add gpio chip Charles Keepax
2015-11-04 19:35 ` Robert Jarzmik
2015-11-05 9:48 ` Charles Keepax
2015-11-06 9:29 ` Lee Jones
2015-11-06 9:27 ` Charles Keepax
2015-11-06 9:48 ` Lee Jones
2015-11-06 20:47 ` Robert Jarzmik
2015-11-06 21:22 ` Mark Brown
2015-11-05 10:26 ` Mark Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1446657164-25012-1-git-send-email-robert.jarzmik@free.fr \
--to=robert.jarzmik@free.fr \
--cc=alsa-devel@alsa-project.org \
--cc=broonie@kernel.org \
--cc=lgirdwood@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=patches@opensource.wolfsonmicro.com \
--cc=perex@perex.cz \
--cc=tiwai@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).