At Sat, 04 Aug 2007 02:51:44 +0200, Gert Robben wrote:
Have you reported this to the ALSA people?
No, I thought this might as well be something for PCI or PM people, and I expected some ALSA people are also reading this list. If not, where else should I report this exactly?
alsa-devel [...] the author of the driver
Done (original message below). Thanks again :)
Gert Robben wrote:
After a suspend-resume cycle (using Suspend2), my sound card doesn't work anymore. It works again after reloading the module.
dmesg, initial boot:
Linux version 2.6.22-ck1
----8<----
PCI driver au8830 lacks driver specific resume support.
dmesg, after resume, trying to use the card:
vortex: ac97 codec stuck busy
Thanks for any help!
Gert Robben
The below is an untested fix. Give it a try.
Takashi
diff -r 23fc708178e1 pci/au88x0/au88x0.c --- a/pci/au88x0/au88x0.c Mon Aug 06 14:05:27 2007 +0200 +++ b/pci/au88x0/au88x0.c Mon Aug 06 15:19:16 2007 +0200 @@ -78,7 +78,7 @@ static void vortex_fix_agp_bridge(struct } }
-static void __devinit snd_vortex_workaround(struct pci_dev *vortex, int fix) +static void snd_vortex_workaround(struct pci_dev *vortex, int fix) { struct pci_dev *via = NULL;
@@ -117,6 +117,50 @@ static void __devinit snd_vortex_workaro pci_dev_put(via); }
+/* + * Power management code + */ +#ifdef CONFIG_PM +static int snd_vortex_suspend(struct pci_dev *pci, pm_message_t state) +{ + struct snd_card *card = pci_get_drvdata(pci); + struct snd_vortex *chip = card->private_data; + int i; + + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + for (i = 0; i < VORTEX_PCM_LAST; i++) + snd_pcm_suspend_all(chip->pcm[i]); + snd_ac97_suspend(chip->codec); + vortex_core_shutdown(chip); + pci_disable_device(pci); + pci_save_state(pci); + return 0; +} + +static int snd_vortex_resume(struct pci_dev *pci) +{ + struct snd_card *card = pci_get_drvdata(pci); + struct snd_vortex *chip = card->private_data; + + pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "au88x0: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } + pci_set_master(pci); + vortex_core_init(chip, 1); + snd_vortex_workaround(pci, chip->pcifix); + snd_ac97_resume(chip->codec); + vortex_connect_default(chip, 1); + vortex_enable_int(chip); + snd_power_change_state(card, SNDRV_CTL_POWER_D0); + return 0; +} +#endif /* CONFIG_PM */ + // component-destructor // (see "Management of Cards and Components") static int snd_vortex_dev_free(struct snd_device *device) @@ -192,7 +236,7 @@ snd_vortex_create(struct snd_card *card, /* Init audio core. * This must be done before we do request_irq otherwise we can get spurious * interupts that we do not handle properly and make a mess of things */ - if ((err = vortex_core_init(chip)) != 0) { + if ((err = vortex_core_init(chip, 0)) != 0) { printk(KERN_ERR "hw core init failed\n"); goto core_out; } @@ -262,7 +306,9 @@ snd_vortex_probe(struct pci_dev *pci, co snd_card_free(card); return err; } - snd_vortex_workaround(pci, pcifix[dev]); + card->private_data = chip; + chip->pcifix = pcifix[dev]; + snd_vortex_workaround(pci, chip->pcifix);
// Card details needed in snd_vortex_midi strcpy(card->driver, CARD_NAME_SHORT); @@ -382,6 +428,10 @@ static struct pci_driver driver = { .id_table = snd_vortex_ids, .probe = snd_vortex_probe, .remove = __devexit_p(snd_vortex_remove), +#ifdef CONFIG_PM + .suspend = snd_vortex_suspend, + .resume = snd_vortex_resume, +#endif };
// initialization of the module diff -r 23fc708178e1 pci/au88x0/au88x0.h --- a/pci/au88x0/au88x0.h Mon Aug 06 14:05:27 2007 +0200 +++ b/pci/au88x0/au88x0.h Mon Aug 06 15:19:16 2007 +0200 @@ -178,7 +178,7 @@ struct snd_vortex { /* PCI hardware resources */ unsigned long io; void __iomem *mmio; - unsigned int irq; + int irq; spinlock_t lock;
/* PCI device */ @@ -186,6 +186,7 @@ struct snd_vortex { u16 vendor; u16 device; u8 rev; + int pcifix; };
/* Functions. */ @@ -233,7 +234,7 @@ static unsigned short vortex_codec_read( static unsigned short vortex_codec_read(struct snd_ac97 * codec, unsigned short addr); static void vortex_spdif_init(vortex_t * vortex, int spdif_sr, int spdif_mode);
-static int vortex_core_init(vortex_t * card); +static int vortex_core_init(vortex_t * card, int do_resume); static int vortex_core_shutdown(vortex_t * card); static void vortex_enable_int(vortex_t * card); static irqreturn_t vortex_interrupt(int irq, void *dev_id); diff -r 23fc708178e1 pci/au88x0/au88x0_a3d.c --- a/pci/au88x0/au88x0_a3d.c Mon Aug 06 14:05:27 2007 +0200 +++ b/pci/au88x0/au88x0_a3d.c Mon Aug 06 15:19:16 2007 +0200 @@ -593,7 +593,7 @@ static int vortex_a3d_register_controls( static int vortex_a3d_register_controls(vortex_t * vortex); static void vortex_a3d_unregister_controls(vortex_t * vortex); /* A3D base support init/shudown */ -static void __devinit vortex_Vort3D_enable(vortex_t * v) +static void vortex_Vort3D_enable(vortex_t * v) { int i;
diff -r 23fc708178e1 pci/au88x0/au88x0_core.c --- a/pci/au88x0/au88x0_core.c Mon Aug 06 14:05:27 2007 +0200 +++ b/pci/au88x0/au88x0_core.c Mon Aug 06 15:19:16 2007 +0200 @@ -2658,7 +2658,7 @@ static void vortex_spdif_init(vortex_t *
/* Initialization */
-static int __devinit vortex_core_init(vortex_t * vortex) +static int vortex_core_init(vortex_t * vortex, int do_resume) {
printk(KERN_INFO "Vortex: init.... "); @@ -2688,7 +2688,8 @@ static int __devinit vortex_core_init(vo vortex_mixer_init(vortex); vortex_srcblock_init(vortex); #ifndef CHIP_AU8820 - vortex_eq_init(vortex); + if (!do_resume) + vortex_eq_init(vortex); vortex_spdif_init(vortex, 48000, 1); vortex_Vort3D_enable(vortex); #endif