MLK-15033: ASoC: ak4458: add pm_runtime support
authorCosmin-Gabriel Samoila <cosmin.samoila@nxp.com>
Thu, 25 Jan 2018 12:36:55 +0000 (14:36 +0200)
committerNitin Garg <nitin.garg@nxp.com>
Tue, 20 Mar 2018 19:53:41 +0000 (14:53 -0500)
Add pm_runtime support for AK4458 codec. Based on latest power
management design in MLK-17074, every driver need to enter
runtime suspend state before entering system suspend, so the
driver should call the pm_runtime_force_suspend in suspend.

Signed-off-by: Cosmin-Gabriel Samoila <cosmin.samoila@nxp.com>
Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
sound/soc/codecs/ak4458-i2c.c
sound/soc/codecs/ak4458.c

index 17d658a..6ddca79 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/i2c.h>
+#include <linux/pm_runtime.h>
 
 #include "ak4458.h"
 
@@ -25,17 +26,26 @@ static int ak4458_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct regmap *regmap;
+       int ret;
 
        regmap = devm_regmap_init_i2c(i2c, &ak4458_i2c_regmap_config);
        if (IS_ERR(regmap))
                return PTR_ERR(regmap);
 
-       return ak4458_probe(&i2c->dev, regmap);
+       ret = ak4458_probe(&i2c->dev, regmap);
+       if (ret)
+               return ret;
+
+       pm_runtime_enable(&i2c->dev);
+
+       return 0;
 }
 
 static int ak4458_i2c_remove(struct i2c_client *i2c)
 {
        ak4458_remove(&i2c->dev);
+       pm_runtime_disable(&i2c->dev);
+
        return 0;
 }
 
index 6471cd0..0d9b5a5 100644 (file)
@@ -31,6 +31,7 @@
 #include <sound/initval.h>
 #include <sound/tlv.h>
 #include <sound/pcm_params.h>
+#include <linux/pm_runtime.h>
 
 #include "ak4458.h"
 
@@ -958,32 +959,48 @@ static int ak4458_codec_remove(struct snd_soc_codec *codec)
        return 0;
 }
 
-static int ak4458_suspend(struct snd_soc_codec *codec)
+#ifdef CONFIG_PM
+static int ak4458_runtime_suspend(struct device *dev)
 {
-       struct ak4458_priv *ak4458 = snd_soc_codec_get_drvdata(codec);
-
-       dev_dbg(codec->dev, "%s(%d)\n", __func__, __LINE__);
+       struct ak4458_priv *ak4458 = dev_get_drvdata(dev);
 
-       ak4458_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       regcache_cache_only(ak4458->regmap, true);
 
-       if (gpio_is_valid(ak4458->pdn_gpio))
+       if (gpio_is_valid(ak4458->pdn_gpio)) {
                gpio_set_value_cansleep(ak4458->pdn_gpio, 0);
+               usleep_range(1000, 2000);
+       }
+
+       if (gpio_is_valid(ak4458->mute_gpio))
+               gpio_set_value_cansleep(ak4458->mute_gpio, 0);
 
        return 0;
 }
 
-static int ak4458_resume(struct snd_soc_codec *codec)
+static int ak4458_runtime_resume(struct device *dev)
 {
-       ak4458_init_reg(codec);
+       struct ak4458_priv *ak4458 = dev_get_drvdata(dev);
 
-       return 0;
+       if (gpio_is_valid(ak4458->mute_gpio))
+               gpio_set_value_cansleep(ak4458->mute_gpio, 1);
+
+       if (gpio_is_valid(ak4458->pdn_gpio)) {
+               gpio_set_value_cansleep(ak4458->pdn_gpio, 0);
+               usleep_range(1000, 2000);
+               gpio_set_value_cansleep(ak4458->pdn_gpio, 1);
+               usleep_range(1000, 2000);
+       }
+
+       regcache_cache_only(ak4458->regmap, false);
+       regcache_mark_dirty(ak4458->regmap);
+
+       return regcache_sync(ak4458->regmap);
 }
+#endif /* CONFIG_PM */
 
 struct snd_soc_codec_driver soc_codec_dev_ak4458 = {
        .probe = ak4458_codec_probe,
        .remove = ak4458_codec_remove,
-       .suspend =      ak4458_suspend,
-       .resume =       ak4458_resume,
        .set_bias_level = ak4458_set_bias_level,
 
        .component_driver = {
@@ -1072,28 +1089,9 @@ void ak4458_remove(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(ak4458_remove);
 
-#if IS_ENABLED(CONFIG_PM)
-static int ak4458_runtime_resume(struct device *dev)
-{
-       struct ak4458_priv *ak4458 = dev_get_drvdata(dev);
-
-       regcache_sync(ak4458->regmap);
-
-       /* TODO Power up*/
-
-       return 0;
-}
-
-static int ak4458_runtime_suspend(struct device *dev)
-{
-       /* TODO Power down */
-
-       return 0;
-}
-#endif
-
 const struct dev_pm_ops ak4458_pm = {
        SET_RUNTIME_PM_OPS(ak4458_runtime_suspend, ak4458_runtime_resume, NULL)
+       SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
 };
 EXPORT_SYMBOL_GPL(ak4458_pm);