]> err.no Git - linux-2.6/commitdiff
[ALSA] Fix missing suspend/resume-code for ens1371
authorKurt J. Bosch <kjb-temp-2005@gmx.de>
Wed, 16 Nov 2005 17:41:21 +0000 (18:41 +0100)
committerJaroslav Kysela <perex@suse.cz>
Tue, 3 Jan 2006 11:16:18 +0000 (12:16 +0100)
Modules: ENS1370/1+ driver

This patch fixes missing suspend/resume-code for snd-ens1371
(but not for snd-ens1370)

Signed-off-by: Kurt J. Bosch <kjb-temp-2005@gmx.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/ens1370.c

index 2daa575f43ff98daf82566054f5e30fbb74411f7..fa619a959d8c5515ee1d324e06c82d9d87127547 100644 (file)
  *
  */
 
+/* Power-Management-Code ( CONFIG_PM )
+ * for ens1371 only ( FIXME )
+ * derived from cs4281.c, atiixp.c and via82xx.c
+ * using http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c1540.htm
+ * by Kurt J. Bosch
+ */
+
 #include <sound/driver.h>
 #include <asm/io.h>
 #include <linux/delay.h>
@@ -1924,6 +1931,117 @@ static struct {
 };
 #endif
 
+static void snd_ensoniq_chip_init(ensoniq_t * ensoniq)
+{
+#ifdef CHIP1371
+       int idx;
+       struct pci_dev *pci = ensoniq->pci;
+#endif
+// this code was part of snd_ensoniq_create before intruduction of suspend/resume
+#ifdef CHIP1370
+       outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
+       outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
+       outl(ES_MEM_PAGEO(ES_PAGE_ADC), ES_REG(ensoniq, MEM_PAGE));
+       outl(ensoniq->dma_bug.addr, ES_REG(ensoniq, PHANTOM_FRAME));
+       outl(0, ES_REG(ensoniq, PHANTOM_COUNT));
+#else
+       outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
+       outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
+       outl(0, ES_REG(ensoniq, 1371_LEGACY));
+       for (idx = 0; es1371_ac97_reset_hack[idx].vid != (unsigned short)PCI_ANY_ID; idx++)
+               if (pci->vendor == es1371_ac97_reset_hack[idx].vid &&
+                   pci->device == es1371_ac97_reset_hack[idx].did &&
+                   ensoniq->rev == es1371_ac97_reset_hack[idx].rev) {
+                       outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
+                       /* need to delay around 20ms(bleech) to give
+                       some CODECs enough time to wakeup */
+                       msleep(20);
+                       break;
+               }
+       /* AC'97 warm reset to start the bitclk */
+       outl(ensoniq->ctrl | ES_1371_SYNC_RES, ES_REG(ensoniq, CONTROL));
+       inl(ES_REG(ensoniq, CONTROL));
+       udelay(20);
+       outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
+       /* Init the sample rate converter */
+       snd_es1371_wait_src_ready(ensoniq);     
+       outl(ES_1371_SRC_DISABLE, ES_REG(ensoniq, 1371_SMPRATE));
+       for (idx = 0; idx < 0x80; idx++)
+               snd_es1371_src_write(ensoniq, idx, 0);
+       snd_es1371_src_write(ensoniq, ES_SMPREG_DAC1 + ES_SMPREG_TRUNC_N, 16 << 4);
+       snd_es1371_src_write(ensoniq, ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS, 16 << 10);
+       snd_es1371_src_write(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_TRUNC_N, 16 << 4);
+       snd_es1371_src_write(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS, 16 << 10);
+       snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC, 1 << 12);
+       snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC + 1, 1 << 12);
+       snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC1, 1 << 12);
+       snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC1 + 1, 1 << 12);
+       snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC2, 1 << 12);
+       snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC2 + 1, 1 << 12);
+       snd_es1371_adc_rate(ensoniq, 22050);
+       snd_es1371_dac1_rate(ensoniq, 22050);
+       snd_es1371_dac2_rate(ensoniq, 22050);
+       /* WARNING:
+        * enabling the sample rate converter without properly programming
+        * its parameters causes the chip to lock up (the SRC busy bit will
+        * be stuck high, and I've found no way to rectify this other than
+        * power cycle) - Thomas Sailer
+        */
+       snd_es1371_wait_src_ready(ensoniq);
+       outl(0, ES_REG(ensoniq, 1371_SMPRATE));
+       /* try reset codec directly */
+       outl(ES_1371_CODEC_WRITE(0, 0), ES_REG(ensoniq, 1371_CODEC));
+#endif
+       outb(ensoniq->uartc = 0x00, ES_REG(ensoniq, UART_CONTROL));
+       outb(0x00, ES_REG(ensoniq, UART_RES));
+       outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
+       synchronize_irq(ensoniq->irq);
+}
+
+#ifdef CONFIG_PM
+static int snd_ensoniq_suspend (snd_card_t * card,
+                                pm_message_t state)
+{
+       ensoniq_t *ensoniq = card->pm_private_data;
+       
+       snd_pcm_suspend_all(ensoniq->pcm1);
+       snd_pcm_suspend_all(ensoniq->pcm2);
+       
+#ifdef CHIP1371        
+       if (ensoniq->u.es1371.ac97)
+               snd_ac97_suspend(ensoniq->u.es1371.ac97);
+#else
+       /* FIXME */
+#endif 
+        pci_set_power_state(ensoniq->pci, 3);
+       pci_disable_device(ensoniq->pci);
+        // snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); // only 2.6.10
+       return 0;
+}
+
+static int snd_ensoniq_resume (snd_card_t * card
+                              )
+{
+       ensoniq_t *ensoniq = card->pm_private_data;
+
+       pci_enable_device(ensoniq->pci);
+       pci_set_power_state(ensoniq->pci, 0);   
+       pci_set_master(ensoniq->pci);
+
+       snd_ensoniq_chip_init(ensoniq);
+
+#ifdef CHIP1371        
+       if (ensoniq->u.es1371.ac97)
+               snd_ac97_resume(ensoniq->u.es1371.ac97);
+#else
+       /* FIXME */
+#endif 
+       // snd_power_change_state(card, SNDRV_CTL_POWER_D0); // only 2.6.10
+       return 0;
+}
+#endif /* CONFIG_PM */
+
+
 static int __devinit snd_ensoniq_create(snd_card_t * card,
                                     struct pci_dev *pci,
                                     ensoniq_t ** rensoniq)
@@ -1986,12 +2104,6 @@ static int __devinit snd_ensoniq_create(snd_card_t * card,
        ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_PCLKDIVO(ES_1370_SRTODIV(8000));
 #endif
        ensoniq->sctrl = 0;
-       /* initialize the chips */
-       outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
-       outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
-       outl(ES_MEM_PAGEO(ES_PAGE_ADC), ES_REG(ensoniq, MEM_PAGE));
-       outl(ensoniq->dma_bug.addr, ES_REG(ensoniq, PHANTOM_FRAME));
-       outl(0, ES_REG(ensoniq, PHANTOM_COUNT));
 #else
        ensoniq->ctrl = 0;
        ensoniq->sctrl = 0;
@@ -2002,59 +2114,16 @@ static int __devinit snd_ensoniq_create(snd_card_t * card,
                        ensoniq->ctrl |= ES_1371_GPIO_OUT(1);   /* turn amplifier on */
                        break;
                }
-       /* initialize the chips */
-       outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
-       outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
-       outl(0, ES_REG(ensoniq, 1371_LEGACY));
        for (idx = 0; es1371_ac97_reset_hack[idx].vid != (unsigned short)PCI_ANY_ID; idx++)
                if (pci->vendor == es1371_ac97_reset_hack[idx].vid &&
                    pci->device == es1371_ac97_reset_hack[idx].did &&
                    ensoniq->rev == es1371_ac97_reset_hack[idx].rev) {
                        ensoniq->cssr |= ES_1371_ST_AC97_RST;
-                       outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
-                       /* need to delay around 20ms(bleech) to give
-                       some CODECs enough time to wakeup */
-                       msleep(20);
                        break;
                }
-       /* AC'97 warm reset to start the bitclk */
-       outl(ensoniq->ctrl | ES_1371_SYNC_RES, ES_REG(ensoniq, CONTROL));
-       inl(ES_REG(ensoniq, CONTROL));
-       udelay(20);
-       outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
-       /* Init the sample rate converter */
-       snd_es1371_wait_src_ready(ensoniq);     
-       outl(ES_1371_SRC_DISABLE, ES_REG(ensoniq, 1371_SMPRATE));
-       for (idx = 0; idx < 0x80; idx++)
-               snd_es1371_src_write(ensoniq, idx, 0);
-       snd_es1371_src_write(ensoniq, ES_SMPREG_DAC1 + ES_SMPREG_TRUNC_N, 16 << 4);
-       snd_es1371_src_write(ensoniq, ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS, 16 << 10);
-       snd_es1371_src_write(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_TRUNC_N, 16 << 4);
-       snd_es1371_src_write(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS, 16 << 10);
-       snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC, 1 << 12);
-       snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC + 1, 1 << 12);
-       snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC1, 1 << 12);
-       snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC1 + 1, 1 << 12);
-       snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC2, 1 << 12);
-       snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC2 + 1, 1 << 12);
-       snd_es1371_adc_rate(ensoniq, 22050);
-       snd_es1371_dac1_rate(ensoniq, 22050);
-       snd_es1371_dac2_rate(ensoniq, 22050);
-       /* WARNING:
-        * enabling the sample rate converter without properly programming
-        * its parameters causes the chip to lock up (the SRC busy bit will
-        * be stuck high, and I've found no way to rectify this other than
-        * power cycle) - Thomas Sailer
-        */
-       snd_es1371_wait_src_ready(ensoniq);
-       outl(0, ES_REG(ensoniq, 1371_SMPRATE));
-       /* try reset codec directly */
-       outl(ES_1371_CODEC_WRITE(0, 0), ES_REG(ensoniq, 1371_CODEC));
 #endif
-       outb(ensoniq->uartc = 0x00, ES_REG(ensoniq, UART_CONTROL));
-       outb(0x00, ES_REG(ensoniq, UART_RES));
-       outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
-       synchronize_irq(ensoniq->irq);
+
+       snd_ensoniq_chip_init(ensoniq);
 
        if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ensoniq, &ops)) < 0) {
                snd_ensoniq_free(ensoniq);
@@ -2063,6 +2132,8 @@ static int __devinit snd_ensoniq_create(snd_card_t * card,
 
        snd_ensoniq_proc_init(ensoniq);
 
+       snd_card_set_pm_callback(card, snd_ensoniq_suspend, snd_ensoniq_resume, ensoniq);
+
        snd_card_set_dev(card, &pci->dev);
 
        *rensoniq = ensoniq;
@@ -2389,6 +2460,7 @@ static struct pci_driver driver = {
        .id_table = snd_audiopci_ids,
        .probe = snd_audiopci_probe,
        .remove = __devexit_p(snd_audiopci_remove),
+       SND_PCI_PM_CALLBACKS
 };
        
 static int __init alsa_card_ens137x_init(void)