#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
#include "ak4458.h"
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;
}
#include <sound/initval.h>
#include <sound/tlv.h>
#include <sound/pcm_params.h>
+#include <linux/pm_runtime.h>
#include "ak4458.h"
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 = {
}
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);