ASoC: wm8804: Add support for hardware reset line
authorCharles Keepax <ckeepax@opensource.wolfsonmicro.com>
Tue, 7 Apr 2015 10:34:50 +0000 (11:34 +0100)
committerMark Brown <broonie@kernel.org>
Tue, 7 Apr 2015 11:36:19 +0000 (12:36 +0100)
It is best to use the physical reset if it is available. This patch adds
support for a GPIO controlled physical reset for the chip.

Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/wm8804.c

index f44da83f50dc85d7e27572b798c965714f873336..cc168c4a4be02227741930e14c171455832d9659 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
+#include <linux/gpio/consumer.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/of_device.h>
@@ -61,6 +62,8 @@ struct wm8804_priv {
        struct regulator_bulk_data supplies[WM8804_NUM_SUPPLIES];
        struct notifier_block disable_nb[WM8804_NUM_SUPPLIES];
        int mclk_div;
+
+       struct gpio_desc *reset;
 };
 
 static int txsrc_get(struct snd_kcontrol *kcontrol,
@@ -182,7 +185,7 @@ static bool wm8804_volatile(struct device *dev, unsigned int reg)
        }
 }
 
-static int wm8804_reset(struct wm8804_priv *wm8804)
+static int wm8804_soft_reset(struct wm8804_priv *wm8804)
 {
        return regmap_write(wm8804->regmap, WM8804_RST_DEVID1, 0x0);
 }
@@ -586,6 +589,14 @@ int wm8804_probe(struct device *dev, struct regmap *regmap)
 
        wm8804->regmap = regmap;
 
+       wm8804->reset = devm_gpiod_get_optional(dev, "wlf,reset",
+                                               GPIOD_OUT_LOW);
+       if (IS_ERR(wm8804->reset)) {
+               ret = PTR_ERR(wm8804->reset);
+               dev_err(dev, "Failed to get reset line: %d\n", ret);
+               return ret;
+       }
+
        for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++)
                wm8804->supplies[i].supply = wm8804_supply_names[i];
 
@@ -620,6 +631,9 @@ int wm8804_probe(struct device *dev, struct regmap *regmap)
                return ret;
        }
 
+       if (wm8804->reset)
+               gpiod_set_value_cansleep(wm8804->reset, 1);
+
        ret = regmap_read(regmap, WM8804_RST_DEVID1, &id1);
        if (ret < 0) {
                dev_err(dev, "Failed to read device ID: %d\n", ret);
@@ -648,10 +662,12 @@ int wm8804_probe(struct device *dev, struct regmap *regmap)
        }
        dev_info(dev, "revision %c\n", id1 + 'A');
 
-       ret = wm8804_reset(wm8804);
-       if (ret < 0) {
-               dev_err(dev, "Failed to issue reset: %d\n", ret);
-               goto err_reg_enable;
+       if (!wm8804->reset) {
+               ret = wm8804_soft_reset(wm8804);
+               if (ret < 0) {
+                       dev_err(dev, "Failed to issue reset: %d\n", ret);
+                       goto err_reg_enable;
+               }
        }
 
        ret = snd_soc_register_codec(dev, &soc_codec_dev_wm8804,