diff options
Diffstat (limited to 'sound/pci/rme96.c')
| -rw-r--r-- | sound/pci/rme96.c | 360 |
1 files changed, 252 insertions, 108 deletions
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index ba894158e76..76169929770 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -28,6 +28,7 @@ #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/module.h> +#include <linux/vmalloc.h> #include <sound/core.h> #include <sound/info.h> @@ -198,6 +199,31 @@ MODULE_PARM_DESC(enable, "Enable RME Digi96 soundcard."); #define RME96_AD1852_VOL_BITS 14 #define RME96_AD1855_VOL_BITS 10 +/* Defines for snd_rme96_trigger */ +#define RME96_TB_START_PLAYBACK 1 +#define RME96_TB_START_CAPTURE 2 +#define RME96_TB_STOP_PLAYBACK 4 +#define RME96_TB_STOP_CAPTURE 8 +#define RME96_TB_RESET_PLAYPOS 16 +#define RME96_TB_RESET_CAPTUREPOS 32 +#define RME96_TB_CLEAR_PLAYBACK_IRQ 64 +#define RME96_TB_CLEAR_CAPTURE_IRQ 128 +#define RME96_RESUME_PLAYBACK (RME96_TB_START_PLAYBACK) +#define RME96_RESUME_CAPTURE (RME96_TB_START_CAPTURE) +#define RME96_RESUME_BOTH (RME96_RESUME_PLAYBACK \ + | RME96_RESUME_CAPTURE) +#define RME96_START_PLAYBACK (RME96_TB_START_PLAYBACK \ + | RME96_TB_RESET_PLAYPOS) +#define RME96_START_CAPTURE (RME96_TB_START_CAPTURE \ + | RME96_TB_RESET_CAPTUREPOS) +#define RME96_START_BOTH (RME96_START_PLAYBACK \ + | RME96_START_CAPTURE) +#define RME96_STOP_PLAYBACK (RME96_TB_STOP_PLAYBACK \ + | RME96_TB_CLEAR_PLAYBACK_IRQ) +#define RME96_STOP_CAPTURE (RME96_TB_STOP_CAPTURE \ + | RME96_TB_CLEAR_CAPTURE_IRQ) +#define RME96_STOP_BOTH (RME96_STOP_PLAYBACK \ + | RME96_STOP_CAPTURE) struct rme96 { spinlock_t lock; @@ -214,6 +240,13 @@ struct rme96 { u8 rev; /* card revision number */ +#ifdef CONFIG_PM_SLEEP + u32 playback_pointer; + u32 capture_pointer; + void *playback_suspend_buffer; + void *capture_suspend_buffer; +#endif + struct snd_pcm_substream *playback_substream; struct snd_pcm_substream *capture_substream; @@ -270,8 +303,7 @@ snd_rme96_playback_pointer(struct snd_pcm_substream *substream); static snd_pcm_uframes_t snd_rme96_capture_pointer(struct snd_pcm_substream *substream); -static void __devinit -snd_rme96_proc_init(struct rme96 *rme96); +static void snd_rme96_proc_init(struct rme96 *rme96); static int snd_rme96_create_switches(struct snd_card *card, @@ -318,9 +350,8 @@ snd_rme96_playback_copy(struct snd_pcm_substream *substream, struct rme96 *rme96 = snd_pcm_substream_chip(substream); count <<= rme96->playback_frlog; pos <<= rme96->playback_frlog; - copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src, - count); - return 0; + return copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src, + count); } static int @@ -333,9 +364,8 @@ snd_rme96_capture_copy(struct snd_pcm_substream *substream, struct rme96 *rme96 = snd_pcm_substream_chip(substream); count <<= rme96->capture_frlog; pos <<= rme96->capture_frlog; - copy_to_user_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos, - count); - return 0; + return copy_to_user_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos, + count); } /* @@ -345,6 +375,8 @@ static struct snd_pcm_hardware snd_rme96_playback_spdif_info = { .info = (SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_SYNC_START | + SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE), .formats = (SNDRV_PCM_FMTBIT_S16_LE | @@ -374,6 +406,8 @@ static struct snd_pcm_hardware snd_rme96_capture_spdif_info = { .info = (SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_SYNC_START | + SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE), .formats = (SNDRV_PCM_FMTBIT_S16_LE | @@ -403,6 +437,8 @@ static struct snd_pcm_hardware snd_rme96_playback_adat_info = { .info = (SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_SYNC_START | + SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE), .formats = (SNDRV_PCM_FMTBIT_S16_LE | @@ -428,6 +464,8 @@ static struct snd_pcm_hardware snd_rme96_capture_adat_info = { .info = (SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_SYNC_START | + SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE), .formats = (SNDRV_PCM_FMTBIT_S16_LE | @@ -1046,54 +1084,35 @@ snd_rme96_capture_hw_params(struct snd_pcm_substream *substream, } static void -snd_rme96_playback_start(struct rme96 *rme96, - int from_pause) +snd_rme96_trigger(struct rme96 *rme96, + int op) { - if (!from_pause) { + if (op & RME96_TB_RESET_PLAYPOS) writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS); - } - - rme96->wcreg |= RME96_WCR_START; - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); -} - -static void -snd_rme96_capture_start(struct rme96 *rme96, - int from_pause) -{ - if (!from_pause) { + if (op & RME96_TB_RESET_CAPTUREPOS) writel(0, rme96->iobase + RME96_IO_RESET_REC_POS); - } - - rme96->wcreg |= RME96_WCR_START_2; + if (op & RME96_TB_CLEAR_PLAYBACK_IRQ) { + rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); + if (rme96->rcreg & RME96_RCR_IRQ) + writel(0, rme96->iobase + RME96_IO_CONFIRM_PLAY_IRQ); + } + if (op & RME96_TB_CLEAR_CAPTURE_IRQ) { + rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); + if (rme96->rcreg & RME96_RCR_IRQ_2) + writel(0, rme96->iobase + RME96_IO_CONFIRM_REC_IRQ); + } + if (op & RME96_TB_START_PLAYBACK) + rme96->wcreg |= RME96_WCR_START; + if (op & RME96_TB_STOP_PLAYBACK) + rme96->wcreg &= ~RME96_WCR_START; + if (op & RME96_TB_START_CAPTURE) + rme96->wcreg |= RME96_WCR_START_2; + if (op & RME96_TB_STOP_CAPTURE) + rme96->wcreg &= ~RME96_WCR_START_2; writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); } -static void -snd_rme96_playback_stop(struct rme96 *rme96) -{ - /* - * Check if there is an unconfirmed IRQ, if so confirm it, or else - * the hardware will not stop generating interrupts - */ - rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); - if (rme96->rcreg & RME96_RCR_IRQ) { - writel(0, rme96->iobase + RME96_IO_CONFIRM_PLAY_IRQ); - } - rme96->wcreg &= ~RME96_WCR_START; - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); -} -static void -snd_rme96_capture_stop(struct rme96 *rme96) -{ - rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); - if (rme96->rcreg & RME96_RCR_IRQ_2) { - writel(0, rme96->iobase + RME96_IO_CONFIRM_REC_IRQ); - } - rme96->wcreg &= ~RME96_WCR_START_2; - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); -} static irqreturn_t snd_rme96_interrupt(int irq, @@ -1156,6 +1175,7 @@ snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream) struct rme96 *rme96 = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; + snd_pcm_set_sync(substream); spin_lock_irq(&rme96->lock); if (rme96->playback_substream != NULL) { spin_unlock_irq(&rme96->lock); @@ -1192,6 +1212,7 @@ snd_rme96_capture_spdif_open(struct snd_pcm_substream *substream) struct rme96 *rme96 = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; + snd_pcm_set_sync(substream); runtime->hw = snd_rme96_capture_spdif_info; if (snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && (rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0) @@ -1223,6 +1244,7 @@ snd_rme96_playback_adat_open(struct snd_pcm_substream *substream) struct rme96 *rme96 = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; + snd_pcm_set_sync(substream); spin_lock_irq(&rme96->lock); if (rme96->playback_substream != NULL) { spin_unlock_irq(&rme96->lock); @@ -1254,6 +1276,7 @@ snd_rme96_capture_adat_open(struct snd_pcm_substream *substream) struct rme96 *rme96 = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; + snd_pcm_set_sync(substream); runtime->hw = snd_rme96_capture_adat_info; if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) { /* makes no sense to use analog input. Note that analog @@ -1289,7 +1312,7 @@ snd_rme96_playback_close(struct snd_pcm_substream *substream) spin_lock_irq(&rme96->lock); if (RME96_ISPLAYING(rme96)) { - snd_rme96_playback_stop(rme96); + snd_rme96_trigger(rme96, RME96_STOP_PLAYBACK); } rme96->playback_substream = NULL; rme96->playback_periodsize = 0; @@ -1310,7 +1333,7 @@ snd_rme96_capture_close(struct snd_pcm_substream *substream) spin_lock_irq(&rme96->lock); if (RME96_ISRECORDING(rme96)) { - snd_rme96_capture_stop(rme96); + snd_rme96_trigger(rme96, RME96_STOP_CAPTURE); } rme96->capture_substream = NULL; rme96->capture_periodsize = 0; @@ -1325,7 +1348,7 @@ snd_rme96_playback_prepare(struct snd_pcm_substream *substream) spin_lock_irq(&rme96->lock); if (RME96_ISPLAYING(rme96)) { - snd_rme96_playback_stop(rme96); + snd_rme96_trigger(rme96, RME96_STOP_PLAYBACK); } writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS); spin_unlock_irq(&rme96->lock); @@ -1339,7 +1362,7 @@ snd_rme96_capture_prepare(struct snd_pcm_substream *substream) spin_lock_irq(&rme96->lock); if (RME96_ISRECORDING(rme96)) { - snd_rme96_capture_stop(rme96); + snd_rme96_trigger(rme96, RME96_STOP_CAPTURE); } writel(0, rme96->iobase + RME96_IO_RESET_REC_POS); spin_unlock_irq(&rme96->lock); @@ -1351,41 +1374,55 @@ snd_rme96_playback_trigger(struct snd_pcm_substream *substream, int cmd) { struct rme96 *rme96 = snd_pcm_substream_chip(substream); + struct snd_pcm_substream *s; + bool sync; + + snd_pcm_group_for_each_entry(s, substream) { + if (snd_pcm_substream_chip(s) == rme96) + snd_pcm_trigger_done(s, substream); + } + + sync = (rme96->playback_substream && rme96->capture_substream) && + (rme96->playback_substream->group == + rme96->capture_substream->group); switch (cmd) { case SNDRV_PCM_TRIGGER_START: if (!RME96_ISPLAYING(rme96)) { - if (substream != rme96->playback_substream) { + if (substream != rme96->playback_substream) return -EBUSY; - } - snd_rme96_playback_start(rme96, 0); + snd_rme96_trigger(rme96, sync ? RME96_START_BOTH + : RME96_START_PLAYBACK); } break; + case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: if (RME96_ISPLAYING(rme96)) { - if (substream != rme96->playback_substream) { + if (substream != rme96->playback_substream) return -EBUSY; - } - snd_rme96_playback_stop(rme96); + snd_rme96_trigger(rme96, sync ? RME96_STOP_BOTH + : RME96_STOP_PLAYBACK); } break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (RME96_ISPLAYING(rme96)) { - snd_rme96_playback_stop(rme96); - } + if (RME96_ISPLAYING(rme96)) + snd_rme96_trigger(rme96, sync ? RME96_STOP_BOTH + : RME96_STOP_PLAYBACK); break; + case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (!RME96_ISPLAYING(rme96)) { - snd_rme96_playback_start(rme96, 1); - } + if (!RME96_ISPLAYING(rme96)) + snd_rme96_trigger(rme96, sync ? RME96_RESUME_BOTH + : RME96_RESUME_PLAYBACK); break; - + default: return -EINVAL; } + return 0; } @@ -1394,38 +1431,51 @@ snd_rme96_capture_trigger(struct snd_pcm_substream *substream, int cmd) { struct rme96 *rme96 = snd_pcm_substream_chip(substream); + struct snd_pcm_substream *s; + bool sync; + + snd_pcm_group_for_each_entry(s, substream) { + if (snd_pcm_substream_chip(s) == rme96) + snd_pcm_trigger_done(s, substream); + } + + sync = (rme96->playback_substream && rme96->capture_substream) && + (rme96->playback_substream->group == + rme96->capture_substream->group); switch (cmd) { case SNDRV_PCM_TRIGGER_START: if (!RME96_ISRECORDING(rme96)) { - if (substream != rme96->capture_substream) { + if (substream != rme96->capture_substream) return -EBUSY; - } - snd_rme96_capture_start(rme96, 0); + snd_rme96_trigger(rme96, sync ? RME96_START_BOTH + : RME96_START_CAPTURE); } break; + case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: if (RME96_ISRECORDING(rme96)) { - if (substream != rme96->capture_substream) { + if (substream != rme96->capture_substream) return -EBUSY; - } - snd_rme96_capture_stop(rme96); + snd_rme96_trigger(rme96, sync ? RME96_STOP_BOTH + : RME96_STOP_CAPTURE); } break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (RME96_ISRECORDING(rme96)) { - snd_rme96_capture_stop(rme96); - } + if (RME96_ISRECORDING(rme96)) + snd_rme96_trigger(rme96, sync ? RME96_STOP_BOTH + : RME96_STOP_CAPTURE); break; + case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (!RME96_ISRECORDING(rme96)) { - snd_rme96_capture_start(rme96, 1); - } + if (!RME96_ISRECORDING(rme96)) + snd_rme96_trigger(rme96, sync ? RME96_RESUME_BOTH + : RME96_RESUME_CAPTURE); break; - + default: return -EINVAL; } @@ -1506,8 +1556,7 @@ snd_rme96_free(void *private_data) return; } if (rme96->irq >= 0) { - snd_rme96_playback_stop(rme96); - snd_rme96_capture_stop(rme96); + snd_rme96_trigger(rme96, RME96_STOP_BOTH); rme96->areg &= ~RME96_AR_DAC_EN; writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); free_irq(rme96->irq, (void *)rme96); @@ -1521,6 +1570,10 @@ snd_rme96_free(void *private_data) pci_release_regions(rme96->pci); rme96->port = 0; } +#ifdef CONFIG_PM_SLEEP + vfree(rme96->playback_suspend_buffer); + vfree(rme96->capture_suspend_buffer); +#endif pci_disable_device(rme96->pci); } @@ -1538,7 +1591,7 @@ snd_rme96_free_adat_pcm(struct snd_pcm *pcm) rme96->adat_pcm = NULL; } -static int __devinit +static int snd_rme96_create(struct rme96 *rme96) { struct pci_dev *pci = rme96->pci; @@ -1556,13 +1609,15 @@ snd_rme96_create(struct rme96 *rme96) rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE); if (!rme96->iobase) { - snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1); + dev_err(rme96->card->dev, + "unable to remap memory region 0x%lx-0x%lx\n", + rme96->port, rme96->port + RME96_IO_SIZE - 1); return -ENOMEM; } if (request_irq(pci->irq, snd_rme96_interrupt, IRQF_SHARED, KBUILD_MODNAME, rme96)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + dev_err(rme96->card->dev, "unable to grab IRQ %d\n", pci->irq); return -EBUSY; } rme96->irq = pci->irq; @@ -1607,8 +1662,7 @@ snd_rme96_create(struct rme96 *rme96) rme96->capture_periodsize = 0; /* make sure playback/capture is stopped, if by some reason active */ - snd_rme96_playback_stop(rme96); - snd_rme96_capture_stop(rme96); + snd_rme96_trigger(rme96, RME96_STOP_BOTH); /* set default values in registers */ rme96->wcreg = @@ -1786,8 +1840,7 @@ snd_rme96_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer } } -static void __devinit -snd_rme96_proc_init(struct rme96 *rme96) +static void snd_rme96_proc_init(struct rme96 *rme96) { struct snd_info_entry *entry; @@ -2321,12 +2374,96 @@ snd_rme96_create_switches(struct snd_card *card, * Card initialisation */ +#ifdef CONFIG_PM_SLEEP + +static int rme96_suspend(struct device *dev) +{ + struct pci_dev *pci = to_pci_dev(dev); + struct snd_card *card = dev_get_drvdata(dev); + struct rme96 *rme96 = card->private_data; + + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + snd_pcm_suspend(rme96->playback_substream); + snd_pcm_suspend(rme96->capture_substream); + + /* save capture & playback pointers */ + rme96->playback_pointer = readl(rme96->iobase + RME96_IO_GET_PLAY_POS) + & RME96_RCR_AUDIO_ADDR_MASK; + rme96->capture_pointer = readl(rme96->iobase + RME96_IO_GET_REC_POS) + & RME96_RCR_AUDIO_ADDR_MASK; + + /* save playback and capture buffers */ + memcpy_fromio(rme96->playback_suspend_buffer, + rme96->iobase + RME96_IO_PLAY_BUFFER, RME96_BUFFER_SIZE); + memcpy_fromio(rme96->capture_suspend_buffer, + rme96->iobase + RME96_IO_REC_BUFFER, RME96_BUFFER_SIZE); + + /* disable the DAC */ + rme96->areg &= ~RME96_AR_DAC_EN; + writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); + + pci_disable_device(pci); + pci_save_state(pci); + + return 0; +} + +static int rme96_resume(struct device *dev) +{ + struct pci_dev *pci = to_pci_dev(dev); + struct snd_card *card = dev_get_drvdata(dev); + struct rme96 *rme96 = card->private_data; + + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + dev_err(dev, "pci_enable_device failed, disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } + + /* reset playback and record buffer pointers */ + writel(0, rme96->iobase + RME96_IO_SET_PLAY_POS + + rme96->playback_pointer); + writel(0, rme96->iobase + RME96_IO_SET_REC_POS + + rme96->capture_pointer); + + /* restore playback and capture buffers */ + memcpy_toio(rme96->iobase + RME96_IO_PLAY_BUFFER, + rme96->playback_suspend_buffer, RME96_BUFFER_SIZE); + memcpy_toio(rme96->iobase + RME96_IO_REC_BUFFER, + rme96->capture_suspend_buffer, RME96_BUFFER_SIZE); + + /* reset the ADC */ + writel(rme96->areg | RME96_AR_PD2, + rme96->iobase + RME96_IO_ADDITIONAL_REG); + writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); + + /* reset and enable DAC, restore analog volume */ + snd_rme96_reset_dac(rme96); + rme96->areg |= RME96_AR_DAC_EN; + writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); + if (RME96_HAS_ANALOG_OUT(rme96)) { + usleep_range(3000, 10000); + snd_rme96_apply_dac_volume(rme96); + } + + snd_power_change_state(card, SNDRV_CTL_POWER_D0); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(rme96_pm, rme96_suspend, rme96_resume); +#define RME96_PM_OPS &rme96_pm +#else +#define RME96_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */ + static void snd_rme96_card_free(struct snd_card *card) { snd_rme96_free(card->private_data); } -static int __devinit +static int snd_rme96_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { @@ -2343,20 +2480,36 @@ snd_rme96_probe(struct pci_dev *pci, dev++; return -ENOENT; } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct rme96), &card); + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct rme96), &card); if (err < 0) return err; card->private_free = snd_rme96_card_free; rme96 = card->private_data; rme96->card = card; rme96->pci = pci; - snd_card_set_dev(card, &pci->dev); if ((err = snd_rme96_create(rme96)) < 0) { snd_card_free(card); return err; } +#ifdef CONFIG_PM_SLEEP + rme96->playback_suspend_buffer = vmalloc(RME96_BUFFER_SIZE); + if (!rme96->playback_suspend_buffer) { + dev_err(card->dev, + "Failed to allocate playback suspend buffer!\n"); + snd_card_free(card); + return -ENOMEM; + } + rme96->capture_suspend_buffer = vmalloc(RME96_BUFFER_SIZE); + if (!rme96->capture_suspend_buffer) { + dev_err(card->dev, + "Failed to allocate capture suspend buffer!\n"); + snd_card_free(card); + return -ENOMEM; + } +#endif + strcpy(card->driver, "Digi96"); switch (rme96->pci->device) { case PCI_DEVICE_ID_RME_DIGI96: @@ -2389,28 +2542,19 @@ snd_rme96_probe(struct pci_dev *pci, return 0; } -static void __devexit snd_rme96_remove(struct pci_dev *pci) +static void snd_rme96_remove(struct pci_dev *pci) { snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); } -static struct pci_driver driver = { +static struct pci_driver rme96_driver = { .name = KBUILD_MODNAME, .id_table = snd_rme96_ids, .probe = snd_rme96_probe, - .remove = __devexit_p(snd_rme96_remove), + .remove = snd_rme96_remove, + .driver = { + .pm = RME96_PM_OPS, + }, }; -static int __init alsa_card_rme96_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_rme96_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_rme96_init) -module_exit(alsa_card_rme96_exit) +module_pci_driver(rme96_driver); |
