diff -Naur a/au88x0/au88x0_a3d.c b/au88x0/au88x0_a3d.c --- a/au88x0/au88x0_a3d.c 2009-04-03 02:55:27.000000000 +0600 +++ b/au88x0/au88x0_a3d.c 2009-04-09 15:56:59.000000000 +0600 @@ -593,7 +593,7 @@ 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 -Naur a/au88x0/au88x0.c b/au88x0/au88x0.c --- a/au88x0/au88x0.c 2009-04-03 02:55:27.000000000 +0600 +++ b/au88x0/au88x0.c 2009-04-10 17:57:10.000000000 +0600 @@ -78,7 +78,7 @@ } } -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,76 @@ 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); + + free_irq(chip->irq, chip); + pci_disable_device(pci); + pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); + + 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); + + /* Init audio core. + * This must be done before we do request_irq otherwise we can get spurious + * interrupts that we do not handle properly and make a mess of things */ + if ((vortex_core_init(chip, 1)) != 0) { + printk(KERN_ERR "hw core init failed\n"); + return -EIO; + } + + if ((request_irq(pci->irq, vortex_interrupt, + IRQF_SHARED, CARD_NAME_SHORT, + chip)) != 0) { + printk(KERN_ERR "cannot grab irq\n"); + return -EIO; + } + chip->irq = pci->irq; + synchronize_irq(chip->irq); + + snd_vortex_workaround(pci, chip->pcifix); + + vortex_connect_default(chip, 1); + vortex_enable_int(chip); + snd_ac97_resume(chip->codec); + synchronize_irq(chip->irq); + 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) @@ -190,7 +260,7 @@ /* Init audio core. * This must be done before we do request_irq otherwise we can get spurious * interrupts 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; } @@ -259,7 +329,11 @@ 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); @@ -379,6 +453,10 @@ .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 -Naur a/au88x0/au88x0_core.c b/au88x0/au88x0_core.c --- a/au88x0/au88x0_core.c 2009-04-03 02:55:27.000000000 +0600 +++ b/au88x0/au88x0_core.c 2009-04-10 21:20:50.000000000 +0600 @@ -2654,7 +2654,7 @@ /* 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.... "); @@ -2684,7 +2684,7 @@ vortex_mixer_init(vortex); vortex_srcblock_init(vortex); #ifndef CHIP_AU8820 - vortex_eq_init(vortex); + vortex_eq_init(vortex, do_resume); vortex_spdif_init(vortex, 48000, 1); vortex_Vort3D_enable(vortex); #endif diff -Naur a/au88x0/au88x0_eq.c b/au88x0/au88x0_eq.c --- a/au88x0/au88x0_eq.c 2009-04-03 02:55:27.000000000 +0600 +++ b/au88x0/au88x0_eq.c 2009-04-09 17:28:58.000000000 +0600 @@ -686,7 +686,7 @@ return (&(eq->coefset)); } #endif -static void vortex_Eqlzr_init(vortex_t * vortex) +static void vortex_Eqlzr_init(vortex_t * vortex, int do_resume) { eqlzr_t *eq = &(vortex->eq); @@ -705,11 +705,14 @@ eq->this5c = 0xffff; /* Set gains. */ + if(!do_resume) memset(eq->this14_array, 0, sizeof(eq->this14_array)); /* Actual init. */ + if(!do_resume) vortex_EqHw_ZeroState(vortex); vortex_EqHw_SetSampleRate(vortex, 0x11); + if(!do_resume) vortex_Eqlzr_ReadAndSetActiveCoefSet(vortex); vortex_EqHw_Program10Band(vortex, &(eq->coefset)); @@ -877,13 +880,14 @@ }; /* ALSA driver entry points. Init and exit. */ -static int __devinit vortex_eq_init(vortex_t * vortex) +static int vortex_eq_init(vortex_t * vortex, int do_resume) { struct snd_kcontrol *kcontrol; int err, i; - vortex_Eqlzr_init(vortex); + vortex_Eqlzr_init(vortex, do_resume); +if(!do_resume){ if ((kcontrol = snd_ctl_new1(&vortex_eqtoggle_kcontrol, vortex)) == NULL) return -ENOMEM; @@ -907,7 +911,7 @@ return -ENOMEM; if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) return err; - +} return 0; } diff -Naur a/au88x0/au88x0.h b/au88x0/au88x0.h --- a/au88x0/au88x0.h 2009-04-03 02:55:27.000000000 +0600 +++ b/au88x0/au88x0.h 2009-04-10 21:20:57.000000000 +0600 @@ -176,7 +176,7 @@ /* PCI hardware resources */ unsigned long io; void __iomem *mmio; - unsigned int irq; + int irq; spinlock_t lock; /* PCI device */ @@ -184,6 +184,7 @@ u16 vendor; u16 device; u8 rev; + int pcifix; }; /* Functions. */ @@ -229,7 +230,7 @@ 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); @@ -275,7 +276,7 @@ static int vortex_gameport_register(vortex_t * card); static void vortex_gameport_unregister(vortex_t * card); #ifndef CHIP_AU8820 -static int vortex_eq_init(vortex_t * vortex); +static int vortex_eq_init(vortex_t * vortex, int do_resume); static int vortex_eq_free(vortex_t * vortex); #endif /* ALSA stuff. */ diff -Naur a/au88x0/au88x0_pcm.c b/au88x0/au88x0_pcm.c --- a/au88x0/au88x0_pcm.c 2009-04-03 02:55:27.000000000 +0600 +++ b/au88x0/au88x0_pcm.c 2009-04-10 21:59:54.000000000 +0600 @@ -187,17 +187,42 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { - vortex_t *chip = snd_pcm_substream_chip(substream); - stream_t *stream = (stream_t *) (substream->runtime->private_data); - int err; + return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); +} - // Alloc buffer memory. - err = - snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - if (err < 0) { - printk(KERN_ERR "Vortex: pcm page alloc failed!\n"); - return err; - } +/* hw_free callback */ +static int snd_vortex_pcm_hw_free(struct snd_pcm_substream *substream) +{ + vortex_t *chip = snd_pcm_substream_chip(substream); + stream_t *stream = (stream_t *) (substream->runtime->private_data); + + spin_lock_irq(&chip->lock); + // Delete audio routes. + if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) { + if (stream != NULL) + vortex_adb_allocroute(chip, stream->dma, + stream->nr_ch, stream->dir, + stream->type); + } +#ifndef CHIP_AU8810 + else { + if (stream != NULL) + vortex_wt_allocroute(chip, stream->dma, 0); + } +#endif + substream->runtime->private_data = NULL; + spin_unlock_irq(&chip->lock); + return snd_pcm_lib_free_pages(substream); +} + +/* prepare callback */ +static int snd_vortex_pcm_prepare(struct snd_pcm_substream *substream) +{ + vortex_t *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + stream_t *stream = (stream_t *) substream->runtime->private_data; + int fmt, dir; + //printk(KERN_INFO "Vortex: pcm_prepare"); /* printk(KERN_INFO "Vortex: periods %d, period_bytes %d, channels = %d\n", params_periods(hw_params), params_period_bytes(hw_params), params_channels(hw_params)); @@ -214,7 +239,7 @@ /* Alloc routes. */ dma = vortex_adb_allocroute(chip, -1, - params_channels(hw_params), + runtime->channels, substream->stream, type); if (dma < 0) { spin_unlock_irq(&chip->lock); @@ -224,81 +249,44 @@ stream->substream = substream; /* Setup Buffers. */ vortex_adbdma_setbuffers(chip, dma, - params_period_bytes(hw_params), - params_periods(hw_params)); + snd_pcm_lib_period_bytes(substream), + runtime->periods); } #ifndef CHIP_AU8810 else { /* if (stream != NULL) vortex_wt_allocroute(chip, substream->number, 0); */ vortex_wt_allocroute(chip, substream->number, - params_channels(hw_params)); + runtime->channels); stream = substream->runtime->private_data = &chip->dma_wt[substream->number]; stream->dma = substream->number; stream->substream = substream; vortex_wtdma_setbuffers(chip, substream->number, - params_period_bytes(hw_params), - params_periods(hw_params)); - } -#endif - spin_unlock_irq(&chip->lock); - return 0; -} - -/* hw_free callback */ -static int snd_vortex_pcm_hw_free(struct snd_pcm_substream *substream) -{ - vortex_t *chip = snd_pcm_substream_chip(substream); - stream_t *stream = (stream_t *) (substream->runtime->private_data); - - spin_lock_irq(&chip->lock); - // Delete audio routes. - if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) { - if (stream != NULL) - vortex_adb_allocroute(chip, stream->dma, - stream->nr_ch, stream->dir, - stream->type); - } -#ifndef CHIP_AU8810 - else { - if (stream != NULL) - vortex_wt_allocroute(chip, stream->dma, 0); + snd_pcm_lib_period_bytes(substream), + runtime->periods); } #endif - substream->runtime->private_data = NULL; - spin_unlock_irq(&chip->lock); - - return snd_pcm_lib_free_pages(substream); -} - -/* prepare callback */ -static int snd_vortex_pcm_prepare(struct snd_pcm_substream *substream) -{ - vortex_t *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - stream_t *stream = (stream_t *) substream->runtime->private_data; - int dma = stream->dma, fmt, dir; - +// spin_unlock_irq(&chip->lock); // set up the hardware with the current configuration. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) dir = 1; else dir = 0; fmt = vortex_alsafmt_aspfmt(runtime->format); - spin_lock_irq(&chip->lock); + if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) { - vortex_adbdma_setmode(chip, dma, 1, dir, fmt, 0 /*? */ , + vortex_adbdma_setmode(chip, stream->dma, 1, dir, fmt, 0 /*? */ , 0); - vortex_adbdma_setstartbuffer(chip, dma, 0); + vortex_adbdma_setstartbuffer(chip, stream->dma, 0); if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_SPDIF) - vortex_adb_setsrc(chip, dma, runtime->rate, dir); + vortex_adb_setsrc(chip, stream->dma, runtime->rate, dir); } #ifndef CHIP_AU8810 else { - vortex_wtdma_setmode(chip, dma, 1, fmt, 0, 0); + vortex_wtdma_setmode(chip, stream->dma, 1, fmt, 0, 0); // FIXME: Set rate (i guess using vortex_wt_writereg() somehow). - vortex_wtdma_setstartbuffer(chip, dma, 0); + vortex_wtdma_setstartbuffer(chip, stream->dma, 0); } #endif spin_unlock_irq(&chip->lock);