ASoC: Implement suspend and resume operations for WM9705
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Thu, 2 Apr 2009 14:49:41 +0000 (15:49 +0100)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Thu, 2 Apr 2009 15:34:37 +0000 (16:34 +0100)
Without this the WM9705 driver fails badly when resuming.

Tested-by: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
sound/soc/codecs/wm9705.c

index 3265817..6e23a81 100644 (file)
@@ -317,6 +317,41 @@ static int wm9705_reset(struct snd_soc_codec *codec)
        return -EIO;
 }
 
+#ifdef CONFIG_PM
+static int wm9705_soc_suspend(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->card->codec;
+
+       soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff);
+
+       return 0;
+}
+
+static int wm9705_soc_resume(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->card->codec;
+       int i, ret;
+       u16 *cache = codec->reg_cache;
+
+       ret = wm9705_reset(codec);
+       if (ret < 0) {
+               printk(KERN_ERR "could not reset AC97 codec\n");
+               return ret;
+       }
+
+       for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) {
+               soc_ac97_ops.write(codec->ac97, i, cache[i>>1]);
+       }
+
+       return 0;
+}
+#else
+#define wm9705_soc_suspend NULL
+#define wm9705_soc_resume NULL
+#endif
+
 static int wm9705_soc_probe(struct platform_device *pdev)
 {
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
@@ -407,6 +442,8 @@ static int wm9705_soc_remove(struct platform_device *pdev)
 struct snd_soc_codec_device soc_codec_dev_wm9705 = {
        .probe =        wm9705_soc_probe,
        .remove =       wm9705_soc_remove,
+       .suspend =      wm9705_soc_suspend,
+       .resume =       wm9705_soc_resume,
 };
 EXPORT_SYMBOL_GPL(soc_codec_dev_wm9705);