ALSA: aureon - Patch for suspend/resume for Terratec Aureon cards.
authorBernhard Urban <lewurm@gmail.com>
Tue, 23 Mar 2010 03:12:38 +0000 (04:12 +0100)
committerTakashi Iwai <tiwai@suse.de>
Tue, 23 Mar 2010 16:34:23 +0000 (17:34 +0100)
Add proper suspend/resume code for Terratec Aureon cards.
Based on ice1724 suspend/resume work of Igor Chernyshev.
Fixes bug https://bugtrack.alsa-project.org/alsa-bug/view.php?id=4944
Tested on linux-2.6.32.9

Signed-off-by: Bernhard Urban <lewurm@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/ice1712/aureon.c

index 9e66f6d..2f62522 100644 (file)
@@ -1956,11 +1956,10 @@ static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
        return 0;
 }
 
-
 /*
- * initialize the chip
+ * reset the chip
  */
-static int __devinit aureon_init(struct snd_ice1712 *ice)
+static int aureon_reset(struct snd_ice1712 *ice)
 {
        static const unsigned short wm_inits_aureon[] = {
                /* These come first to reduce init pop noise */
@@ -2047,30 +2046,10 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
                0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
                (unsigned short)-1
        };
-       struct aureon_spec *spec;
        unsigned int tmp;
        const unsigned short *p;
-       int err, i;
-
-       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (!spec)
-               return -ENOMEM;
-       ice->spec = spec;
-
-       if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
-               ice->num_total_dacs = 6;
-               ice->num_total_adcs = 2;
-       } else {
-               /* aureon 7.1 and prodigy 7.1 */
-               ice->num_total_dacs = 8;
-               ice->num_total_adcs = 2;
-       }
-
-       /* to remeber the register values of CS8415 */
-       ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
-       if (!ice->akm)
-               return -ENOMEM;
-       ice->akm_codecs = 1;
+       int err;
+       struct aureon_spec *spec = ice->spec;
 
        err = aureon_ac97_init(ice);
        if (err != 0)
@@ -2118,6 +2097,61 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
        /* initialize PCA9554 pin directions & set default input */
        aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
        aureon_pca9554_write(ice, PCA9554_OUT, 0x00);   /* internal AUX */
+       return 0;
+}
+
+/*
+ * suspend/resume
+ */
+#ifdef CONFIG_PM
+static int aureon_resume(struct snd_ice1712 *ice)
+{
+       struct aureon_spec *spec = ice->spec;
+       int err, i;
+
+       err = aureon_reset(ice);
+       if (err != 0)
+               return err;
+
+       /* workaround for poking volume with alsamixer after resume:
+        * just set stored volume again */
+       for (i = 0; i < ice->num_total_dacs; i++)
+               wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
+       return 0;
+}
+#endif
+
+/*
+ * initialize the chip
+ */
+static int __devinit aureon_init(struct snd_ice1712 *ice)
+{
+       struct aureon_spec *spec;
+       int i, err;
+
+       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+       if (!spec)
+               return -ENOMEM;
+       ice->spec = spec;
+
+       if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
+               ice->num_total_dacs = 6;
+               ice->num_total_adcs = 2;
+       } else {
+               /* aureon 7.1 and prodigy 7.1 */
+               ice->num_total_dacs = 8;
+               ice->num_total_adcs = 2;
+       }
+
+       /* to remeber the register values of CS8415 */
+       ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
+       if (!ice->akm)
+               return -ENOMEM;
+       ice->akm_codecs = 1;
+
+       err = aureon_reset(ice);
+       if (err != 0)
+               return err;
 
        spec->master[0] = WM_VOL_MUTE;
        spec->master[1] = WM_VOL_MUTE;
@@ -2126,6 +2160,11 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
                wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
        }
 
+#ifdef CONFIG_PM
+       ice->pm_resume = aureon_resume;
+       ice->pm_suspend_enabled = 1;
+#endif
+
        return 0;
 }