ALSA: snd-ad1816a: Implement suspend/resume
authorOndrej Zary <linux@rainbow-software.org>
Sun, 19 Aug 2012 21:27:26 +0000 (23:27 +0200)
committerTakashi Iwai <tiwai@suse.de>
Mon, 20 Aug 2012 09:12:56 +0000 (11:12 +0200)
Implement suspend/resume support for AD1816 chips.
Tested with Terratec SoundSystem Base-1.

Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
include/sound/ad1816a.h
sound/isa/ad1816a/ad1816a.c
sound/isa/ad1816a/ad1816a_lib.c

index 62da41e..2a89f0d 100644 (file)
@@ -147,6 +147,9 @@ struct snd_ad1816a {
        unsigned int c_dma_size;
 
        struct snd_timer *timer;
+#ifdef CONFIG_PM
+       unsigned short image[48];
+#endif
 };
 
 
@@ -171,5 +174,9 @@ extern int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm
 extern int snd_ad1816a_mixer(struct snd_ad1816a *chip);
 extern int snd_ad1816a_timer(struct snd_ad1816a *chip, int device,
                             struct snd_timer **rtimer);
+#ifdef CONFIG_PM
+extern void snd_ad1816a_suspend(struct snd_ad1816a *chip);
+extern void snd_ad1816a_resume(struct snd_ad1816a *chip);
+#endif
 
 #endif /* __SOUND_AD1816A_H */
index 1a374e6..2c2f829 100644 (file)
@@ -244,13 +244,37 @@ static void __devexit snd_ad1816a_pnp_remove(struct pnp_card_link * pcard)
        pnp_set_card_drvdata(pcard, NULL);
 }
 
+#ifdef CONFIG_PM
+static int snd_ad1816a_pnp_suspend(struct pnp_card_link *pcard,
+                                  pm_message_t state)
+{
+       struct snd_card *card = pnp_get_card_drvdata(pcard);
+
+       snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+       snd_ad1816a_suspend(card->private_data);
+       return 0;
+}
+
+static int snd_ad1816a_pnp_resume(struct pnp_card_link *pcard)
+{
+       struct snd_card *card = pnp_get_card_drvdata(pcard);
+
+       snd_ad1816a_resume(card->private_data);
+       snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+       return 0;
+}
+#endif
+
 static struct pnp_card_driver ad1816a_pnpc_driver = {
        .flags          = PNP_DRIVER_RES_DISABLE,
        .name           = "ad1816a",
        .id_table       = snd_ad1816a_pnpids,
        .probe          = snd_ad1816a_pnp_detect,
        .remove         = __devexit_p(snd_ad1816a_pnp_remove),
-       /* FIXME: suspend/resume */
+#ifdef CONFIG_PM
+       .suspend        = snd_ad1816a_pnp_suspend,
+       .resume         = snd_ad1816a_pnp_resume,
+#endif
 };
 
 static int __init alsa_card_ad1816a_init(void)
index de5cc1c..db64df6 100644 (file)
@@ -491,7 +491,7 @@ static int snd_ad1816a_capture_close(struct snd_pcm_substream *substream)
 }
 
 
-static void __devinit snd_ad1816a_init(struct snd_ad1816a *chip)
+static void snd_ad1816a_init(struct snd_ad1816a *chip)
 {
        unsigned long flags;
 
@@ -511,6 +511,32 @@ static void __devinit snd_ad1816a_init(struct snd_ad1816a *chip)
        spin_unlock_irqrestore(&chip->lock, flags);
 }
 
+#ifdef CONFIG_PM
+void snd_ad1816a_suspend(struct snd_ad1816a *chip)
+{
+       int reg;
+       unsigned long flags;
+
+       snd_pcm_suspend_all(chip->pcm);
+       spin_lock_irqsave(&chip->lock, flags);
+       for (reg = 0; reg < 48; reg++)
+               chip->image[reg] = snd_ad1816a_read(chip, reg);
+       spin_unlock_irqrestore(&chip->lock, flags);
+}
+
+void snd_ad1816a_resume(struct snd_ad1816a *chip)
+{
+       int reg;
+       unsigned long flags;
+
+       snd_ad1816a_init(chip);
+       spin_lock_irqsave(&chip->lock, flags);
+       for (reg = 0; reg < 48; reg++)
+               snd_ad1816a_write(chip, reg, chip->image[reg]);
+       spin_unlock_irqrestore(&chip->lock, flags);
+}
+#endif
+
 static int __devinit snd_ad1816a_probe(struct snd_ad1816a *chip)
 {
        unsigned long flags;