All of lore.kernel.org
 help / color / mirror / Atom feed
* Changed ens1370.c to enable Suspend ens1371
@ 2005-11-11 17:58 Kurt J. Bosch
  2005-11-11 18:06 ` Takashi Iwai
  0 siblings, 1 reply; 9+ messages in thread
From: Kurt J. Bosch @ 2005-11-11 17:58 UTC (permalink / raw)
  To: alsa-devel

[-- Attachment #1: Type: text/plain, Size: 1205 bytes --]

Hi,

I changed driver ens1371 to enable suspend to disk
only using some other drivers as kind of templates.
(No special handling of any registers added.)

BTW - this is my second post. The first is holded back since Nov. 6th 
because it was too big. - I'm sorry about that, but i'm a newbe here :-)

I did some testing on Ubuntu Breezy
Linux version 2.6.12-9-686 (buildd@rothera) (gcc version 3.4.5 20050809
(prerelease) (Ubuntu 3.4.4-6ubuntu8)) #1 Mon Oct 10 13:25:32 BST 2005
alsa 1.0.9b
and it seems to work fine for me.

I am using swsusp not swsusp2
but with script hibernate 1.07
and removed snd-ens1371 from /etc/hibernate/blacklisted-modules
thus it is not longer unloaded.

To avoid problems with dmix I changed /etc/hibernate/hibernate.conf :
--8<--
### misclaunch
# OnSuspend 20 echo "Good night!"
# OnResume 20 echo "Good morning!"
#
# kjb - workaround for
# ALSA Bug  0001249: dmix doesn't survive suspend to RAM
# this restores the socket /tmp/alsa-dmix-... (!)
OnSuspend 20 sudo -H -u kurt /usr/bin/esdctl standby
OnResume 20 sudo -H -u kurt /usr/bin/esdctl resume
--8<--
(I use gnome, so esd is running all the time.)


patch for ens1370.c CVS revision 1.90

is appended

Any comments ?



[-- Attachment #2: patch.diff --]
[-- Type: text/x-patch, Size: 8402 bytes --]

21a22,28
> /* 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 ( kjb )
>  */
> 
786a794
> 	case SNDRV_PCM_TRIGGER_RESUME:  // kjb
787a796
> 	case SNDRV_PCM_TRIGGER_SUSPEND: // kjb
806c815,817
< 		if (cmd == SNDRV_PCM_TRIGGER_START)
---
> 		if (cmd == SNDRV_PCM_TRIGGER_START
> 		 || cmd == SNDRV_PCM_TRIGGER_RESUME // kjb
> 		   )
1014c1025,1027
< 				 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_SYNC_START),
---
> 				 SNDRV_PCM_INFO_PAUSE |
> 				 SNDRV_PCM_INFO_RESUME | // kjb
> 				 SNDRV_PCM_INFO_SYNC_START),
1040c1053,1055
< 				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE | 
---
> 				 SNDRV_PCM_INFO_MMAP_VALID | 
> 				 SNDRV_PCM_INFO_PAUSE |
> 				 SNDRV_PCM_INFO_RESUME | // kjb
1060c1075,1077
< 				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),
---
> 				 SNDRV_PCM_INFO_MMAP_VALID | 
>  				 SNDRV_PCM_INFO_RESUME | // kjb
> 				 SNDRV_PCM_INFO_SYNC_START),
1926a1944,2056
> /* initialize the chips */
> // kjb - this code was part of snd_ensoniq_create
> static void snd_ensoniq_chip_init(ensoniq_t * ensoniq)
> {
> #ifdef CHIP1371
> 	int idx;
> 	struct pci_dev *pci = ensoniq->pci;
> #endif
> #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) {
> 			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);
> }
> 
> #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 */
> 
> 
1989,1994d2118
< 	/* 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));
2005,2052d2128
< 	/* 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));
2054,2057c2130,2131
< 	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); // kjb
2065a2140,2143
> #ifdef CHIP1371 /* FIXME */
> 	snd_card_set_pm_callback(card, snd_ensoniq_suspend, snd_ensoniq_resume, ensoniq); // kjb
> #endif
> 
2392a2471
> 	SND_PCI_PM_CALLBACKS // kjb

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Changed ens1370.c to enable Suspend ens1371
  2005-11-11 17:58 Changed ens1370.c to enable Suspend ens1371 Kurt J. Bosch
@ 2005-11-11 18:06 ` Takashi Iwai
  2005-11-14 12:05   ` Kurt J. Bosch
  0 siblings, 1 reply; 9+ messages in thread
From: Takashi Iwai @ 2005-11-11 18:06 UTC (permalink / raw)
  To: Kurt J. Bosch; +Cc: alsa-devel

At Fri, 11 Nov 2005 18:58:20 +0100,
Kurt J. Bosch wrote:
> 
> Hi,
> 
> I changed driver ens1371 to enable suspend to disk
> only using some other drivers as kind of templates.
> (No special handling of any registers added.)
> 
> BTW - this is my second post. The first is holded back since Nov. 6th 
> because it was too big. - I'm sorry about that, but i'm a newbe here :-)
> 
> I did some testing on Ubuntu Breezy
> Linux version 2.6.12-9-686 (buildd@rothera) (gcc version 3.4.5 20050809
> (prerelease) (Ubuntu 3.4.4-6ubuntu8)) #1 Mon Oct 10 13:25:32 BST 2005
> alsa 1.0.9b
> and it seems to work fine for me.
> 
> I am using swsusp not swsusp2
> but with script hibernate 1.07
> and removed snd-ens1371 from /etc/hibernate/blacklisted-modules
> thus it is not longer unloaded.
> 
> To avoid problems with dmix I changed /etc/hibernate/hibernate.conf :
> --8<--
> ### misclaunch
> # OnSuspend 20 echo "Good night!"
> # OnResume 20 echo "Good morning!"
> #
> # kjb - workaround for
> # ALSA Bug  0001249: dmix doesn't survive suspend to RAM
> # this restores the socket /tmp/alsa-dmix-... (!)
> OnSuspend 20 sudo -H -u kurt /usr/bin/esdctl standby
> OnResume 20 sudo -H -u kurt /usr/bin/esdctl resume
> --8<--
> (I use gnome, so esd is running all the time.)
> 
> 
> patch for ens1370.c CVS revision 1.90
> 
> is appended
> 
> Any comments ?

Thanks for the patch.  But, please make a patch with diff -u.

The pcm info flag SNDRV_PCM_INFO_RESUME can't be set in your case.

This INFO_RESUME flag means that the full suspend/resume is supported.
That is, the PCM stream is resumed fully only by calling
snd_pcm_trigger(RESUME) without snd_pcm_prepare(), etc.

In your case, it's a partial suspend/resume support.  That is, the
resume is done by explicitly calling snd_pcm_prepare() snd restart
from the app.

Also, add a proper changelog with signed-off-by line.  It's like
below:

	Summary: Fix blah ...

	This patch fixes blah blah...
	...

	Signed-off-by: Foo Bar <foo@bar.com>



Thanks,

Takashi


-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP.  Click here to play: http://sourceforge.net/geronimo.php

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Changed ens1370.c to enable Suspend ens1371
  2005-11-11 18:06 ` Takashi Iwai
@ 2005-11-14 12:05   ` Kurt J. Bosch
  2005-11-14 12:25     ` Kurt J. Bosch
  2005-11-14 17:02     ` Takashi Iwai
  0 siblings, 2 replies; 9+ messages in thread
From: Kurt J. Bosch @ 2005-11-14 12:05 UTC (permalink / raw)
  To: alsa-devel

[-- Attachment #1: Type: text/plain, Size: 1666 bytes --]



Takashi Iwai schrieb:
> At Fri, 11 Nov 2005 18:58:20 +0100,
> Kurt J. Bosch wrote:
> 
>>Hi,
>>
>>I changed driver ens1371 to enable suspend to disk
>>only using some other drivers as kind of templates.
>>(No special handling of any registers added.)
>>
>>I did some testing on Ubuntu Breezy
>>Linux version 2.6.12-9-686 (buildd@rothera) (gcc version 3.4.5 20050809
>>(prerelease) (Ubuntu 3.4.4-6ubuntu8)) #1 Mon Oct 10 13:25:32 BST 2005
>>alsa 1.0.9b
and on Ubuntu Breezy with the kernel from Hoary
Linux version 2.6.10-5-686 (buildd@terranova) (gcc version 3.3.5 (Debian 
1:3.3.5-8ubuntu2)) #1 Mon Oct 10 11:28:02 UTC 2005
(which I use most time)
>>and it seems to work fine for me.
>>
>>I am using swsusp not swsusp2
>>but with script hibernate 1.07
>>and removed snd-ens1371 from /etc/hibernate/blacklisted-modules
>>thus it is not longer unloaded.
>>
>>patch for ens1370.c CVS revision 1.90
>>
>>is appended
patchs for kernels 2.6.12 and 2.6.10 too :)
> 
> 
> Thanks for the patch.  But, please make a patch with diff -u.
> 
> The pcm info flag SNDRV_PCM_INFO_RESUME can't be set in your case.
> 
> This INFO_RESUME flag means that the full suspend/resume is supported.
> That is, the PCM stream is resumed fully only by calling
> snd_pcm_trigger(RESUME) without snd_pcm_prepare(), etc.
> 
> In your case, it's a partial suspend/resume support.  That is, the
> resume is done by explicitly calling snd_pcm_prepare() snd restart
> from the app.
> 
> Also, add a proper changelog with signed-off-by line.  It's like
> below:
> 
> 	Summary: Fix blah ...
> 
> 	This patch fixes blah blah...
> 	...
> 
> 	Signed-off-by: Foo Bar <foo@bar.com>
> 
ok - I fixed that



[-- Attachment #2: ens1370.c_2.6.10_ens1371_suspend.patch --]
[-- Type: text/x-patch, Size: 9309 bytes --]

Summary: Fix missing suspend/resume-code for ens1371

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>

--- 2.6.10-5-686/ens1370.org.c	2004-12-24 22:35:24.000000000 +0100
+++ 2.6.10-5-686/ens1370.c	2005-11-14 11:36:58.000000000 +0100
@@ -19,6 +19,14 @@
  *
  */
 
+/* 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>
@@ -1875,6 +1883,129 @@
 };
 #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
+#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) {
+		        unsigned long tmo;
+			signed long tmo2;
+
+			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 */
+			tmo = jiffies + (HZ / 50) + 1;
+			while (1) {
+				tmo2 = tmo - jiffies;
+				if (tmo2 <= 0)
+					break;
+				set_current_state(TASK_UNINTERRUPTIBLE);
+				schedule_timeout(tmo2);
+			}
+			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,
+                                unsigned int 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);
+	return 0;
+}
+
+static int snd_ensoniq_resume (snd_card_t * card,
+                               unsigned int state)
+{
+	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);
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+
 static int __devinit snd_ensoniq_create(snd_card_t * card,
 				     struct pci_dev *pci,
 				     ensoniq_t ** rensoniq)
@@ -1938,12 +2069,6 @@
 	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;
@@ -1954,74 +2079,17 @@
 			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) {
-		        unsigned long tmo;
-			signed long tmo2;
-
-			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 */
-			tmo = jiffies + (HZ / 50) + 1;
-			while (1) {
-				tmo2 = tmo - jiffies;
-				if (tmo2 <= 0)
-					break;
-				set_current_state(TASK_UNINTERRUPTIBLE);
-				schedule_timeout(tmo2);
-			}
-			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);
 		return err;
 	}
+#ifdef CHIP1371 /* FIXME - this should apply to 1370 too as soon as 1370-suspend-code is written by some one :) */
+	snd_card_set_pm_callback(card, snd_ensoniq_suspend, snd_ensoniq_resume, ensoniq);
+#endif
 
 	snd_card_set_dev(card, &pci->dev);
 
@@ -2342,7 +2410,7 @@
 		card->driver,
 		ensoniq->port,
 		ensoniq->irq);
-
+		
 	if ((err = snd_card_register(card)) < 0) {
 		snd_card_free(card);
 		return err;
@@ -2364,6 +2432,9 @@
 	.id_table = snd_audiopci_ids,
 	.probe = snd_audiopci_probe,
 	.remove = __devexit_p(snd_audiopci_remove),
+#ifdef CHIP1371 /* FIXME - this should apply to 1370 too as soon as 1370-suspend-code is written by some one :) */
+	SND_PCI_PM_CALLBACKS
+#endif
 };
 	
 static int __init alsa_card_ens137x_init(void)

[-- Attachment #3: ens1370.c_2.6.12_ens1371_suspend.patch --]
[-- Type: text/x-patch, Size: 8025 bytes --]

Summary: Fix missing suspend/resume-code for ens1371

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>

--- 2.6.12-9-686/ens1370.org.c	2005-10-10 14:12:34.000000000 +0200
+++ 2.6.12-9-686/ens1370.c	2005-11-14 11:22:48.000000000 +0100
@@ -19,6 +19,13 @@
  *
  */
 
+/* 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>
@@ -1922,85 +1929,20 @@
 };
 #endif
 
-static int __devinit snd_ensoniq_create(snd_card_t * card,
-				     struct pci_dev *pci,
-				     ensoniq_t ** rensoniq)
+static void snd_ensoniq_chip_init(ensoniq_t * ensoniq)
 {
-	ensoniq_t *ensoniq;
-	unsigned short cmdw;
-	unsigned char cmdb;
 #ifdef CHIP1371
 	int idx;
+	struct pci_dev *pci = ensoniq->pci;
 #endif
-	int err;
-	static snd_device_ops_t ops = {
-		.dev_free =	snd_ensoniq_dev_free,
-	};
-
-	*rensoniq = NULL;
-	if ((err = pci_enable_device(pci)) < 0)
-		return err;
-	ensoniq = kcalloc(1, sizeof(*ensoniq), GFP_KERNEL);
-	if (ensoniq == NULL) {
-		pci_disable_device(pci);
-		return -ENOMEM;
-	}
-	spin_lock_init(&ensoniq->reg_lock);
-	init_MUTEX(&ensoniq->src_mutex);
-	ensoniq->card = card;
-	ensoniq->pci = pci;
-	ensoniq->irq = -1;
-	if ((err = pci_request_regions(pci, "Ensoniq AudioPCI")) < 0) {
-		kfree(ensoniq);
-		pci_disable_device(pci);
-		return err;
-	}
-	ensoniq->port = pci_resource_start(pci, 0);
-	if (request_irq(pci->irq, snd_audiopci_interrupt, SA_INTERRUPT|SA_SHIRQ, "Ensoniq AudioPCI", (void *)ensoniq)) {
-		snd_printk("unable to grab IRQ %d\n", pci->irq);
-		snd_ensoniq_free(ensoniq);
-		return -EBUSY;
-	}
-	ensoniq->irq = pci->irq;
-#ifdef CHIP1370
-	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
-				16, &ensoniq->dma_bug) < 0) {
-		snd_printk("unable to allocate space for phantom area - dma_bug\n");
-		snd_ensoniq_free(ensoniq);
-		return -EBUSY;
-	}
-#endif
-	pci_set_master(pci);
-	pci_read_config_byte(pci, PCI_REVISION_ID, &cmdb);
-	ensoniq->rev = cmdb;
-	pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &cmdw);
-	ensoniq->subsystem_vendor_id = cmdw;
-	pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &cmdw);
-	ensoniq->subsystem_device_id = cmdw;
+// this code was part of snd_ensoniq_create before introduction of suspend/resume
 #ifdef CHIP1370
-#if 0
-	ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_SERR_DISABLE | ES_1370_PCLKDIVO(ES_1370_SRTODIV(8000));
-#else	/* get microphone working */
-	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;
-	ensoniq->cssr = 0;
-	for (idx = 0; es1371_amplifier_hack[idx].svid != (unsigned short)PCI_ANY_ID; idx++)
-		if (ensoniq->subsystem_vendor_id == es1371_amplifier_hack[idx].svid &&
-		    ensoniq->subsystem_device_id == es1371_amplifier_hack[idx].sdid) {
-			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));
@@ -2062,7 +2004,129 @@
 	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)
+{
+	ensoniq_t *ensoniq;
+	unsigned short cmdw;
+	unsigned char cmdb;
+#ifdef CHIP1371
+	int idx;
+#endif
+	int err;
+	static snd_device_ops_t ops = {
+		.dev_free =	snd_ensoniq_dev_free,
+	};
+
+	*rensoniq = NULL;
+	if ((err = pci_enable_device(pci)) < 0)
+		return err;
+	ensoniq = kcalloc(1, sizeof(*ensoniq), GFP_KERNEL);
+	if (ensoniq == NULL) {
+		pci_disable_device(pci);
+		return -ENOMEM;
+	}
+	spin_lock_init(&ensoniq->reg_lock);
+	init_MUTEX(&ensoniq->src_mutex);
+	ensoniq->card = card;
+	ensoniq->pci = pci;
+	ensoniq->irq = -1;
+	if ((err = pci_request_regions(pci, "Ensoniq AudioPCI")) < 0) {
+		kfree(ensoniq);
+		pci_disable_device(pci);
+		return err;
+	}
+	ensoniq->port = pci_resource_start(pci, 0);
+	if (request_irq(pci->irq, snd_audiopci_interrupt, SA_INTERRUPT|SA_SHIRQ, "Ensoniq AudioPCI", (void *)ensoniq)) {
+		snd_printk("unable to grab IRQ %d\n", pci->irq);
+		snd_ensoniq_free(ensoniq);
+		return -EBUSY;
+	}
+	ensoniq->irq = pci->irq;
+#ifdef CHIP1370
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				16, &ensoniq->dma_bug) < 0) {
+		snd_printk("unable to allocate space for phantom area - dma_bug\n");
+		snd_ensoniq_free(ensoniq);
+		return -EBUSY;
+	}
+#endif
+	pci_set_master(pci);
+	pci_read_config_byte(pci, PCI_REVISION_ID, &cmdb);
+	ensoniq->rev = cmdb;
+	pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &cmdw);
+	ensoniq->subsystem_vendor_id = cmdw;
+	pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &cmdw);
+	ensoniq->subsystem_device_id = cmdw;
+#ifdef CHIP1370
+#if 0
+	ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_SERR_DISABLE | ES_1370_PCLKDIVO(ES_1370_SRTODIV(8000));
+#else	/* get microphone working */
+	ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_PCLKDIVO(ES_1370_SRTODIV(8000));
+#endif
+	ensoniq->sctrl = 0;
+#else
+	ensoniq->ctrl = 0;
+	ensoniq->sctrl = 0;
+	ensoniq->cssr = 0;
+	for (idx = 0; es1371_amplifier_hack[idx].svid != (unsigned short)PCI_ANY_ID; idx++)
+		if (ensoniq->subsystem_vendor_id == es1371_amplifier_hack[idx].svid &&
+		    ensoniq->subsystem_device_id == es1371_amplifier_hack[idx].sdid) {
+			ensoniq->ctrl |= ES_1371_GPIO_OUT(1);	/* turn amplifier on */
+			break;
+		}
+#endif
+
+	snd_ensoniq_chip_init(ensoniq);
 
 	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ensoniq, &ops)) < 0) {
 		snd_ensoniq_free(ensoniq);
@@ -2071,6 +2135,10 @@
 
 	snd_ensoniq_proc_init(ensoniq);
 
+#ifdef CHIP1371 /* FIXME - this should apply to 1370 too as soon as 1370-suspend-code is written by some one :) */
+	snd_card_set_pm_callback(card, snd_ensoniq_suspend, snd_ensoniq_resume, ensoniq);
+#endif
+
 	snd_card_set_dev(card, &pci->dev);
 
 	*rensoniq = ensoniq;
@@ -2397,6 +2465,9 @@
 	.id_table = snd_audiopci_ids,
 	.probe = snd_audiopci_probe,
 	.remove = __devexit_p(snd_audiopci_remove),
+#ifdef CHIP1371 /* FIXME - this should apply to 1370 too as soon as 1370-suspend-code is written by some one :) */
+	SND_PCI_PM_CALLBACKS
+#endif
 };
 	
 static int __init alsa_card_ens137x_init(void)

[-- Attachment #4: ens1370.c_CVS_rev_1.90_ens1371_suspend.patch --]
[-- Type: text/x-patch, Size: 8787 bytes --]

Summary: Fix missing suspend/resume-code for ens1371

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>

--- CVS/ens1370.CVS-rev-1.90.c	2005-11-06 11:11:38.000000000 +0100
+++ CVS/ens1370.c	2005-11-14 11:21:58.000000000 +0100
@@ -19,6 +19,13 @@
  *
  */
 
+/* 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,118 @@
 };
 #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) {
+			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);
+}
+
+#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 +2105,6 @@
 	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 +2115,9 @@
 			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 +2126,10 @@
 
 	snd_ensoniq_proc_init(ensoniq);
 
+#ifdef CHIP1371 /* FIXME - this should apply to 1370 too as soon as 1370-suspend-code is written by some one :) */
+	snd_card_set_pm_callback(card, snd_ensoniq_suspend, snd_ensoniq_resume, ensoniq);
+#endif
+
 	snd_card_set_dev(card, &pci->dev);
 
 	*rensoniq = ensoniq;
@@ -2390,6 +2457,9 @@
 	.id_table = snd_audiopci_ids,
 	.probe = snd_audiopci_probe,
 	.remove = __devexit_p(snd_audiopci_remove),
+#ifdef CHIP1371 /* FIXME - this should apply to 1370 too as soon as 1370-suspend-code is written by some one :) */
+	SND_PCI_PM_CALLBACKS
+#endif
 };
 	
 static int __init alsa_card_ens137x_init(void)

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Changed ens1370.c to enable Suspend ens1371
  2005-11-14 12:05   ` Kurt J. Bosch
@ 2005-11-14 12:25     ` Kurt J. Bosch
  2005-11-14 17:02     ` Takashi Iwai
  1 sibling, 0 replies; 9+ messages in thread
From: Kurt J. Bosch @ 2005-11-14 12:25 UTC (permalink / raw)
  To: alsa-devel

BTW theres a bug-report for this too:
https://bugtrack.alsa-project.org/alsa-bug/view.php?id=1355



-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP.  Click here to play: http://sourceforge.net/geronimo.php

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Changed ens1370.c to enable Suspend ens1371
  2005-11-14 12:05   ` Kurt J. Bosch
  2005-11-14 12:25     ` Kurt J. Bosch
@ 2005-11-14 17:02     ` Takashi Iwai
  2005-11-16 13:03       ` Kurt J. Bosch
  1 sibling, 1 reply; 9+ messages in thread
From: Takashi Iwai @ 2005-11-14 17:02 UTC (permalink / raw)
  To: Kurt J. Bosch; +Cc: alsa-devel

At Mon, 14 Nov 2005 13:05:30 +0100,
Kurt J. Bosch wrote:
> 
> Summary: Fix missing suspend/resume-code for ens1371
> 
> 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>
> 
> --- 2.6.10-5-686/ens1370.org.c	2004-12-24 22:35:24.000000000 +0100
> +++ 2.6.10-5-686/ens1370.c	2005-11-14 11:36:58.000000000 +0100
> @@ -19,6 +19,14 @@
>   *
>   */
>  
> +/* 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>
> @@ -1875,6 +1883,129 @@
>  };
>  #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
> +#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) {
> +		        unsigned long tmo;
> +			signed long tmo2;
> +
> +			ensoniq->cssr |= ES_1371_ST_AC97_RST;


ensoniq->cssr shouldn't be overridden here.

> +static int snd_ensoniq_resume (snd_card_t * card,
> +                               unsigned int state)
> +{
> +	ensoniq_t *ensoniq = card->pm_private_data;
> +
> +	pci_enable_device(ensoniq->pci);
> +        pci_set_power_state(ensoniq->pci, 0);	
> +	pci_set_master(ensoniq->pci);

Don't mix up tab and spaces.

> +#ifdef CHIP1371 /* FIXME - this should apply to 1370 too as soon as 1370-suspend-code is written by some one :) */
> +	snd_card_set_pm_callback(card, snd_ensoniq_suspend, snd_ensoniq_resume, ensoniq);
> +#endif

It's still better than nothing.  Better to remove this ifdef.


> @@ -2364,6 +2432,9 @@
>  	.id_table = snd_audiopci_ids,
>  	.probe = snd_audiopci_probe,
>  	.remove = __devexit_p(snd_audiopci_remove),
> +#ifdef CHIP1371 /* FIXME - this should apply to 1370 too as soon as 1370-suspend-code is written by some one :) */
> +	SND_PCI_PM_CALLBACKS
> +#endif

Ditto.


Takashi


-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP.  Click here to play: http://sourceforge.net/geronimo.php

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Changed ens1370.c to enable Suspend ens1371
  2005-11-14 17:02     ` Takashi Iwai
@ 2005-11-16 13:03       ` Kurt J. Bosch
  2005-11-16 13:14         ` Takashi Iwai
  0 siblings, 1 reply; 9+ messages in thread
From: Kurt J. Bosch @ 2005-11-16 13:03 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel

[-- Attachment #1: Type: text/plain, Size: 2866 bytes --]



Takashi Iwai schrieb:
> At Mon, 14 Nov 2005 13:05:30 +0100,
> Kurt J. Bosch wrote:
> 
>>Summary: Fix missing suspend/resume-code for ens1371
>>
>>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>
>>
>>--- 2.6.10-5-686/ens1370.org.c	2004-12-24 22:35:24.000000000 +0100
>>+++ 2.6.10-5-686/ens1370.c	2005-11-14 11:36:58.000000000 +0100
>>@@ -19,6 +19,14 @@
>>  *
>>  */
>> 
>>+/* 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>
>>@@ -1875,6 +1883,129 @@
>> };
>> #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
>>+#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) {
>>+		        unsigned long tmo;
>>+			signed long tmo2;
>>+
>>+			ensoniq->cssr |= ES_1371_ST_AC97_RST;
> 
> 
> 
> ensoniq->cssr shouldn't be overridden here.
> 
> 
>>+static int snd_ensoniq_resume (snd_card_t * card,
>>+                               unsigned int state)
>>+{
>>+	ensoniq_t *ensoniq = card->pm_private_data;
>>+
>>+	pci_enable_device(ensoniq->pci);
>>+        pci_set_power_state(ensoniq->pci, 0);	
>>+	pci_set_master(ensoniq->pci);
> 
> 
> Don't mix up tab and spaces.
> 
> 
>>+#ifdef CHIP1371 /* FIXME - this should apply to 1370 too as soon as 1370-suspend-code is written by some one :) */
>>+	snd_card_set_pm_callback(card, snd_ensoniq_suspend, snd_ensoniq_resume, ensoniq);
>>+#endif
> 
> 
> It's still better than nothing.  Better to remove this ifdef.
> 
> 
> 
>>@@ -2364,6 +2432,9 @@
>> 	.id_table = snd_audiopci_ids,
>> 	.probe = snd_audiopci_probe,
>> 	.remove = __devexit_p(snd_audiopci_remove),
>>+#ifdef CHIP1371 /* FIXME - this should apply to 1370 too as soon as 1370-suspend-code is written by some one :) */
>>+	SND_PCI_PM_CALLBACKS
>>+#endif
> 
> 
> Ditto.
> 
> 
OK - fixed that too

[-- Attachment #2: ens1370.c_2.6.10_ens1371_suspend.patch --]
[-- Type: text/x-patch, Size: 9045 bytes --]

Summary: Fix missing suspend/resume-code for ens1371

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>

--- 2.6.10-5-686/ens1370.org.c	2004-12-24 22:35:24.000000000 +0100
+++ 2.6.10-5-686/ens1370.c	2005-11-16 12:05:36.000000000 +0100
@@ -19,6 +19,14 @@
  *
  */
 
+/* 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>
@@ -1875,6 +1883,128 @@
 };
 #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 introduction 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) {
+		        unsigned long tmo;
+			signed long tmo2;
+
+			outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
+			/* need to delay around 20ms(bleech) to give
+			some CODECs enough time to wakeup */
+			tmo = jiffies + (HZ / 50) + 1;
+			while (1) {
+				tmo2 = tmo - jiffies;
+				if (tmo2 <= 0)
+					break;
+				set_current_state(TASK_UNINTERRUPTIBLE);
+				schedule_timeout(tmo2);
+			}
+			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,
+                                unsigned int 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);
+	return 0;
+}
+
+static int snd_ensoniq_resume (snd_card_t * card,
+                               unsigned int state)
+{
+	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);
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+
 static int __devinit snd_ensoniq_create(snd_card_t * card,
 				     struct pci_dev *pci,
 				     ensoniq_t ** rensoniq)
@@ -1938,12 +2068,6 @@
 	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;
@@ -1954,74 +2078,22 @@
 			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) {
-		        unsigned long tmo;
-			signed long tmo2;
-
 			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 */
-			tmo = jiffies + (HZ / 50) + 1;
-			while (1) {
-				tmo2 = tmo - jiffies;
-				if (tmo2 <= 0)
-					break;
-				set_current_state(TASK_UNINTERRUPTIBLE);
-				schedule_timeout(tmo2);
-			}
 			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);
 		return err;
 	}
+	snd_card_set_pm_callback(card, snd_ensoniq_suspend, snd_ensoniq_resume, ensoniq);
 
 	snd_card_set_dev(card, &pci->dev);
 
@@ -2342,7 +2414,7 @@
 		card->driver,
 		ensoniq->port,
 		ensoniq->irq);
-
+		
 	if ((err = snd_card_register(card)) < 0) {
 		snd_card_free(card);
 		return err;
@@ -2364,6 +2436,7 @@
 	.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)

[-- Attachment #3: ens1370.c_2.6.12_ens1371_suspend.patch --]
[-- Type: text/x-patch, Size: 8958 bytes --]

Summary: Fix missing suspend/resume-code for ens1371

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>

--- 2.6.12-9-686/ens1370.org.c	2005-10-10 14:12:34.000000000 +0200
+++ 2.6.12-9-686/ens1370.c	2005-11-16 12:04:04.000000000 +0100
@@ -19,6 +19,13 @@
  *
  */
 
+/* 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>
@@ -1922,6 +1929,128 @@
 };
 #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 introduction 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) {
+		        unsigned long tmo;
+			signed long tmo2;
+
+			outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
+			/* need to delay around 20ms(bleech) to give
+			some CODECs enough time to wakeup */
+			tmo = jiffies + (HZ / 50) + 1;
+			while (1) {
+				tmo2 = tmo - jiffies;
+				if (tmo2 <= 0)
+					break;
+				set_current_state(TASK_UNINTERRUPTIBLE);
+				schedule_timeout(tmo2);
+			}
+			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)
@@ -1984,12 +2113,6 @@
 	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;
@@ -2000,69 +2123,16 @@
 			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) {
-		        unsigned long tmo;
-			signed long tmo2;
-
 			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 */
-			tmo = jiffies + (HZ / 50) + 1;
-			while (1) {
-				tmo2 = tmo - jiffies;
-				if (tmo2 <= 0)
-					break;
-				set_current_state(TASK_UNINTERRUPTIBLE);
-				schedule_timeout(tmo2);
-			}
 			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);
@@ -2071,6 +2141,8 @@
 
 	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;
@@ -2397,6 +2469,7 @@
 	.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)

[-- Attachment #4: ens1370.c_CVS_rev_1.90_ens1371_suspend.patch --]
[-- Type: text/x-patch, Size: 8505 bytes --]

Summary: Fix missing suspend/resume-code for ens1371

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>

--- Alsa_CVS_rev_1.90/ens1370.org.c	2005-11-06 11:11:38.000000000 +0100
+++ Alsa_CVS_rev_1.90/ens1370.c	2005-11-16 12:06:08.000000000 +0100
@@ -19,6 +19,13 @@
  *
  */
 
+/* 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 @@
 };
 #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 @@
 	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 @@
 			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 @@
 
 	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;
@@ -2390,6 +2461,7 @@
 	.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)

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Changed ens1370.c to enable Suspend ens1371
  2005-11-16 13:03       ` Kurt J. Bosch
@ 2005-11-16 13:14         ` Takashi Iwai
  2005-11-16 15:04           ` Thierry Vignaud
  0 siblings, 1 reply; 9+ messages in thread
From: Takashi Iwai @ 2005-11-16 13:14 UTC (permalink / raw)
  To: Kurt J. Bosch; +Cc: alsa-devel

At Wed, 16 Nov 2005 14:03:56 +0100,
Kurt J. Bosch wrote:
> 
> OK - fixed that too

Thanks.  I'll apply it after 1.0.10-final is released.
I also have a PM code for ak4531, so ens1370 should work, too.  It'll
be merged together.


Takashi


-------------------------------------------------------
This SF.Net email is sponsored by the JBoss Inc.  Get Certified Today
Register for a JBoss Training Course.  Free Certification Exam
for All Training Attendees Through End of 2005. For more info visit:
http://ads.osdn.com/?ad_id=7628&alloc_id=16845&op=click

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Changed ens1370.c to enable Suspend ens1371
  2005-11-16 13:14         ` Takashi Iwai
@ 2005-11-16 15:04           ` Thierry Vignaud
  2005-11-16 15:16             ` Jaroslav Kysela
  0 siblings, 1 reply; 9+ messages in thread
From: Thierry Vignaud @ 2005-11-16 15:04 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel

Takashi Iwai <tiwai@suse.de> writes:

> Thanks.  I'll apply it after 1.0.10-final is released.

btw, CVS is tagged so when will it be released?



-------------------------------------------------------
This SF.Net email is sponsored by the JBoss Inc.  Get Certified Today
Register for a JBoss Training Course.  Free Certification Exam
for All Training Attendees Through End of 2005. For more info visit:
http://ads.osdn.com/?ad_id=7628&alloc_id=16845&op=click

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Changed ens1370.c to enable Suspend ens1371
  2005-11-16 15:04           ` Thierry Vignaud
@ 2005-11-16 15:16             ` Jaroslav Kysela
  0 siblings, 0 replies; 9+ messages in thread
From: Jaroslav Kysela @ 2005-11-16 15:16 UTC (permalink / raw)
  To: Thierry Vignaud; +Cc: Takashi Iwai, alsa-devel

On Wed, 16 Nov 2005, Thierry Vignaud wrote:

> Takashi Iwai <tiwai@suse.de> writes:
> 
> > Thanks.  I'll apply it after 1.0.10-final is released.
> 
> btw, CVS is tagged so when will it be released?

In a few hours. The packages are building now, so after testing from the 
ALSA team, the 1.0.10-final will be out.

						Jaroslav

-----
Jaroslav Kysela <perex@suse.cz>
Linux Kernel Sound Maintainer
ALSA Project, SUSE Labs


-------------------------------------------------------
This SF.Net email is sponsored by the JBoss Inc.  Get Certified Today
Register for a JBoss Training Course.  Free Certification Exam
for All Training Attendees Through End of 2005. For more info visit:
http://ads.osdn.com/?ad_id=7628&alloc_id=16845&op=click

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2005-11-16 15:16 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-11-11 17:58 Changed ens1370.c to enable Suspend ens1371 Kurt J. Bosch
2005-11-11 18:06 ` Takashi Iwai
2005-11-14 12:05   ` Kurt J. Bosch
2005-11-14 12:25     ` Kurt J. Bosch
2005-11-14 17:02     ` Takashi Iwai
2005-11-16 13:03       ` Kurt J. Bosch
2005-11-16 13:14         ` Takashi Iwai
2005-11-16 15:04           ` Thierry Vignaud
2005-11-16 15:16             ` Jaroslav Kysela

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.