diff options
Diffstat (limited to 'sound/pci/cs4281.c')
| -rw-r--r-- | sound/pci/cs4281.c | 288 |
1 files changed, 93 insertions, 195 deletions
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index ec4247638fa1..d00b2c9fb1e3 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -1,22 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Driver for Cirrus Logic CS4281 based PCI soundcard * Copyright (c) by Jaroslav Kysela <perex@perex.cz>, - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * */ #include <linux/io.h> @@ -40,7 +25,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); MODULE_DESCRIPTION("Cirrus Logic CS4281"); MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,CS4281}}"); static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ @@ -486,10 +470,7 @@ struct cs4281 { struct gameport *gameport; -#ifdef CONFIG_PM_SLEEP u32 suspend_regs[SUSPEND_REGISTERS]; -#endif - }; static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id); @@ -670,7 +651,7 @@ static int snd_cs4281_trigger(struct snd_pcm_substream *substream, int cmd) struct cs4281_dma *dma = substream->runtime->private_data; struct cs4281 *chip = snd_pcm_substream_chip(substream); - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_PAUSE_PUSH: dma->valDCR |= BA0_DCR_MSK; @@ -697,19 +678,17 @@ static int snd_cs4281_trigger(struct snd_pcm_substream *substream, int cmd) dma->valFCR &= ~BA0_FCR_FEN; break; default: - spin_unlock(&chip->reg_lock); return -EINVAL; } snd_cs4281_pokeBA0(chip, dma->regDMR, dma->valDMR); snd_cs4281_pokeBA0(chip, dma->regFCR, dma->valFCR); snd_cs4281_pokeBA0(chip, dma->regDCR, dma->valDCR); - spin_unlock(&chip->reg_lock); return 0; } static unsigned int snd_cs4281_rate(unsigned int rate, unsigned int *real_rate) { - unsigned int val = ~0; + unsigned int val; if (real_rate) *real_rate = rate; @@ -722,9 +701,8 @@ static unsigned int snd_cs4281_rate(unsigned int rate, unsigned int *real_rate) case 44100: return 1; case 48000: return 0; default: - goto __variable; + break; } - __variable: val = 1536000 / rate; if (real_rate) *real_rate = 1536000 / val; @@ -796,26 +774,14 @@ static void snd_cs4281_mode(struct cs4281 *chip, struct cs4281_dma *dma, snd_cs4281_pokeBA0(chip, dma->regFSIC, 0); } -static int snd_cs4281_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_cs4281_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - static int snd_cs4281_playback_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct cs4281_dma *dma = runtime->private_data; struct cs4281 *chip = snd_pcm_substream_chip(substream); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); snd_cs4281_mode(chip, dma, runtime, 0, 1); - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -825,9 +791,8 @@ static int snd_cs4281_capture_prepare(struct snd_pcm_substream *substream) struct cs4281_dma *dma = runtime->private_data; struct cs4281 *chip = snd_pcm_substream_chip(substream); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); snd_cs4281_mode(chip, dma, runtime, 1, 1); - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -954,9 +919,6 @@ static int snd_cs4281_capture_close(struct snd_pcm_substream *substream) static const struct snd_pcm_ops snd_cs4281_playback_ops = { .open = snd_cs4281_playback_open, .close = snd_cs4281_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cs4281_hw_params, - .hw_free = snd_cs4281_hw_free, .prepare = snd_cs4281_playback_prepare, .trigger = snd_cs4281_trigger, .pointer = snd_cs4281_pointer, @@ -965,9 +927,6 @@ static const struct snd_pcm_ops snd_cs4281_playback_ops = { static const struct snd_pcm_ops snd_cs4281_capture_ops = { .open = snd_cs4281_capture_open, .close = snd_cs4281_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cs4281_hw_params, - .hw_free = snd_cs4281_hw_free, .prepare = snd_cs4281_capture_prepare, .trigger = snd_cs4281_trigger, .pointer = snd_cs4281_pointer, @@ -987,11 +946,11 @@ static int snd_cs4281_pcm(struct cs4281 *chip, int device) pcm->private_data = chip; pcm->info_flags = 0; - strcpy(pcm->name, "CS4281"); + strscpy(pcm->name, "CS4281"); chip->pcm = pcm; - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), 64*1024, 512*1024); + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &chip->pci->dev, + 64*1024, 512*1024); return 0; } @@ -1097,28 +1056,33 @@ static int snd_cs4281_mixer(struct cs4281 *chip) struct snd_card *card = chip->card; struct snd_ac97_template ac97; int err; - static struct snd_ac97_bus_ops ops = { + static const struct snd_ac97_bus_ops ops = { .write = snd_cs4281_ac97_write, .read = snd_cs4281_ac97_read, }; - if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0) + err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus); + if (err < 0) return err; chip->ac97_bus->private_free = snd_cs4281_mixer_free_ac97_bus; memset(&ac97, 0, sizeof(ac97)); ac97.private_data = chip; ac97.private_free = snd_cs4281_mixer_free_ac97; - if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) + err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97); + if (err < 0) return err; if (chip->dual_codec) { ac97.num = 1; - if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97_secondary)) < 0) + err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97_secondary); + if (err < 0) return err; } - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4281_fm_vol, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4281_fm_vol, chip)); + if (err < 0) return err; - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4281_pcm_vol, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4281_pcm_vol, chip)); + if (err < 0) return err; return 0; } @@ -1162,11 +1126,11 @@ static ssize_t snd_cs4281_BA1_read(struct snd_info_entry *entry, return count; } -static struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 = { +static const struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 = { .read = snd_cs4281_BA0_read, }; -static struct snd_info_entry_ops snd_cs4281_proc_ops_BA1 = { +static const struct snd_info_entry_ops snd_cs4281_proc_ops_BA1 = { .read = snd_cs4281_BA1_read, }; @@ -1174,8 +1138,7 @@ static void snd_cs4281_proc_init(struct cs4281 *chip) { struct snd_info_entry *entry; - if (! snd_card_proc_new(chip->card, "cs4281", &entry)) - snd_info_set_text_ops(entry, chip, snd_cs4281_proc_read); + snd_card_ro_proc_new(chip->card, "cs4281", chip, snd_cs4281_proc_read); if (! snd_card_proc_new(chip->card, "cs4281_BA0", &entry)) { entry->content = SNDRV_INFO_CONTENT_DATA; entry->private_data = chip; @@ -1298,12 +1261,11 @@ static inline int snd_cs4281_create_gameport(struct cs4281 *chip) { return -ENOS static inline void snd_cs4281_free_gameport(struct cs4281 *chip) { } #endif /* IS_REACHABLE(CONFIG_GAMEPORT) */ -static int snd_cs4281_free(struct cs4281 *chip) +static void snd_cs4281_free(struct snd_card *card) { - snd_cs4281_free_gameport(chip); + struct cs4281 *chip = card->private_data; - if (chip->irq >= 0) - synchronize_irq(chip->irq); + snd_cs4281_free_gameport(chip); /* Mask interrupts */ snd_cs4281_pokeBA0(chip, BA0_HIMR, 0x7fffffff); @@ -1311,48 +1273,20 @@ static int snd_cs4281_free(struct cs4281 *chip) snd_cs4281_pokeBA0(chip, BA0_CLKCR1, 0); /* Sound System Power Management - Turn Everything OFF */ snd_cs4281_pokeBA0(chip, BA0_SSPM, 0); - /* PCI interface - D3 state */ - pci_set_power_state(chip->pci, PCI_D3hot); - - if (chip->irq >= 0) - free_irq(chip->irq, chip); - iounmap(chip->ba0); - iounmap(chip->ba1); - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - - kfree(chip); - return 0; -} - -static int snd_cs4281_dev_free(struct snd_device *device) -{ - struct cs4281 *chip = device->device_data; - return snd_cs4281_free(chip); } static int snd_cs4281_chip_init(struct cs4281 *chip); /* defined below */ static int snd_cs4281_create(struct snd_card *card, struct pci_dev *pci, - struct cs4281 **rchip, int dual_codec) { - struct cs4281 *chip; - unsigned int tmp; + struct cs4281 *chip = card->private_data; int err; - static struct snd_device_ops ops = { - .dev_free = snd_cs4281_dev_free, - }; - *rchip = NULL; - if ((err = pci_enable_device(pci)) < 0) + err = pcim_enable_device(pci); + if (err < 0) return err; - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } spin_lock_init(&chip->reg_lock); chip->card = card; chip->pci = pci; @@ -1364,43 +1298,30 @@ static int snd_cs4281_create(struct snd_card *card, } chip->dual_codec = dual_codec; - if ((err = pci_request_regions(pci, "CS4281")) < 0) { - kfree(chip); - pci_disable_device(pci); - return err; - } + chip->ba0 = pcim_iomap_region(pci, 0, "CS4281"); + if (IS_ERR(chip->ba0)) + return PTR_ERR(chip->ba0); chip->ba0_addr = pci_resource_start(pci, 0); - chip->ba1_addr = pci_resource_start(pci, 1); - chip->ba0 = pci_ioremap_bar(pci, 0); - chip->ba1 = pci_ioremap_bar(pci, 1); - if (!chip->ba0 || !chip->ba1) { - snd_cs4281_free(chip); - return -ENOMEM; - } + chip->ba1 = pcim_iomap_region(pci, 1, "CS4281"); + if (IS_ERR(chip->ba1)) + return PTR_ERR(chip->ba1); + chip->ba1_addr = pci_resource_start(pci, 1); - if (request_irq(pci->irq, snd_cs4281_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip)) { + if (devm_request_irq(&pci->dev, pci->irq, snd_cs4281_interrupt, + IRQF_SHARED, KBUILD_MODNAME, chip)) { dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); - snd_cs4281_free(chip); return -ENOMEM; } chip->irq = pci->irq; + card->sync_irq = chip->irq; + card->private_free = snd_cs4281_free; - tmp = snd_cs4281_chip_init(chip); - if (tmp) { - snd_cs4281_free(chip); - return tmp; - } - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_cs4281_free(chip); + err = snd_cs4281_chip_init(chip); + if (err) return err; - } snd_cs4281_proc_init(chip); - - *rchip = chip; return 0; } @@ -1432,12 +1353,14 @@ static int snd_cs4281_chip_init(struct cs4281 *chip) * space between 0e4h and 0ffh to be written. */ snd_cs4281_pokeBA0(chip, BA0_CWPR, 0x4281); - if ((tmp = snd_cs4281_peekBA0(chip, BA0_SERC1)) != (BA0_SERC1_SO1EN | BA0_SERC1_AC97)) { + tmp = snd_cs4281_peekBA0(chip, BA0_SERC1); + if (tmp != (BA0_SERC1_SO1EN | BA0_SERC1_AC97)) { dev_err(chip->card->dev, "SERC1 AC'97 check failed (0x%x)\n", tmp); return -EIO; } - if ((tmp = snd_cs4281_peekBA0(chip, BA0_SERC2)) != (BA0_SERC2_SI1EN | BA0_SERC2_AC97)) { + tmp = snd_cs4281_peekBA0(chip, BA0_SERC2); + if (tmp != (BA0_SERC2_SI1EN | BA0_SERC2_AC97)) { dev_err(chip->card->dev, "SERC2 AC'97 check failed (0x%x)\n", tmp); return -EIO; @@ -1634,7 +1557,6 @@ static int snd_cs4281_chip_init(struct cs4281 *chip) BA0_HISR_DMA(1) | BA0_HISR_DMA(2) | BA0_HISR_DMA(3))); - synchronize_irq(chip->irq); return 0; } @@ -1654,7 +1576,7 @@ static int snd_cs4281_midi_input_open(struct snd_rawmidi_substream *substream) { struct cs4281 *chip = substream->rmidi->private_data; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); chip->midcr |= BA0_MIDCR_RXE; chip->midi_input = substream; if (!(chip->uartm & CS4281_MODE_OUTPUT)) { @@ -1662,7 +1584,6 @@ static int snd_cs4281_midi_input_open(struct snd_rawmidi_substream *substream) } else { snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); } - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -1670,7 +1591,7 @@ static int snd_cs4281_midi_input_close(struct snd_rawmidi_substream *substream) { struct cs4281 *chip = substream->rmidi->private_data; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); chip->midcr &= ~(BA0_MIDCR_RXE | BA0_MIDCR_RIE); chip->midi_input = NULL; if (!(chip->uartm & CS4281_MODE_OUTPUT)) { @@ -1679,7 +1600,6 @@ static int snd_cs4281_midi_input_close(struct snd_rawmidi_substream *substream) snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); } chip->uartm &= ~CS4281_MODE_INPUT; - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -1687,7 +1607,7 @@ static int snd_cs4281_midi_output_open(struct snd_rawmidi_substream *substream) { struct cs4281 *chip = substream->rmidi->private_data; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); chip->uartm |= CS4281_MODE_OUTPUT; chip->midcr |= BA0_MIDCR_TXE; chip->midi_output = substream; @@ -1696,7 +1616,6 @@ static int snd_cs4281_midi_output_open(struct snd_rawmidi_substream *substream) } else { snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); } - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -1704,7 +1623,7 @@ static int snd_cs4281_midi_output_close(struct snd_rawmidi_substream *substream) { struct cs4281 *chip = substream->rmidi->private_data; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); chip->midcr &= ~(BA0_MIDCR_TXE | BA0_MIDCR_TIE); chip->midi_output = NULL; if (!(chip->uartm & CS4281_MODE_INPUT)) { @@ -1713,16 +1632,14 @@ static int snd_cs4281_midi_output_close(struct snd_rawmidi_substream *substream) snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); } chip->uartm &= ~CS4281_MODE_OUTPUT; - spin_unlock_irq(&chip->reg_lock); return 0; } static void snd_cs4281_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) { - unsigned long flags; struct cs4281 *chip = substream->rmidi->private_data; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (up) { if ((chip->midcr & BA0_MIDCR_RIE) == 0) { chip->midcr |= BA0_MIDCR_RIE; @@ -1734,16 +1651,14 @@ static void snd_cs4281_midi_input_trigger(struct snd_rawmidi_substream *substrea snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); } } - spin_unlock_irqrestore(&chip->reg_lock, flags); } static void snd_cs4281_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) { - unsigned long flags; struct cs4281 *chip = substream->rmidi->private_data; unsigned char byte; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); if (up) { if ((chip->midcr & BA0_MIDCR_TIE) == 0) { chip->midcr |= BA0_MIDCR_TIE; @@ -1764,7 +1679,6 @@ static void snd_cs4281_midi_output_trigger(struct snd_rawmidi_substream *substre snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); } } - spin_unlock_irqrestore(&chip->reg_lock, flags); } static const struct snd_rawmidi_ops snd_cs4281_midi_output = @@ -1786,9 +1700,10 @@ static int snd_cs4281_midi(struct cs4281 *chip, int device) struct snd_rawmidi *rmidi; int err; - if ((err = snd_rawmidi_new(chip->card, "CS4281", device, 1, 1, &rmidi)) < 0) + err = snd_rawmidi_new(chip->card, "CS4281", device, 1, 1, &rmidi); + if (err < 0) return err; - strcpy(rmidi->name, "CS4281"); + strscpy(rmidi->name, "CS4281"); snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_cs4281_midi_output); snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_cs4281_midi_input); rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; @@ -1816,10 +1731,12 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id) } if (status & (BA0_HISR_DMA(0)|BA0_HISR_DMA(1)|BA0_HISR_DMA(2)|BA0_HISR_DMA(3))) { - for (dma = 0; dma < 4; dma++) + for (dma = 0; dma < 4; dma++) { + bool period_elapsed = false; + cdma = &chip->dma[dma]; + if (status & BA0_HISR_DMA(dma)) { - cdma = &chip->dma[dma]; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); /* ack DMA IRQ */ val = snd_cs4281_peekBA0(chip, cdma->regHDSR); /* workaround, sometimes CS4281 acknowledges */ @@ -1828,24 +1745,24 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id) if ((val & BA0_HDSR_DHTC) && !(cdma->frag & 1)) { cdma->frag--; chip->spurious_dhtc_irq++; - spin_unlock(&chip->reg_lock); continue; } if ((val & BA0_HDSR_DTC) && (cdma->frag & 1)) { cdma->frag--; chip->spurious_dtc_irq++; - spin_unlock(&chip->reg_lock); continue; } - spin_unlock(&chip->reg_lock); - snd_pcm_period_elapsed(cdma->substream); + period_elapsed = true; } + if (period_elapsed) + snd_pcm_period_elapsed(cdma->substream); + } } if ((status & BA0_HISR_MIDI) && chip->rmidi) { unsigned char c; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); while ((snd_cs4281_peekBA0(chip, BA0_MIDSR) & BA0_MIDSR_RBE) == 0) { c = snd_cs4281_peekBA0(chip, BA0_MIDRP); if ((chip->midcr & BA0_MIDCR_RIE) == 0) @@ -1862,7 +1779,6 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id) } snd_cs4281_pokeBA0(chip, BA0_MIDWP, c); } - spin_unlock(&chip->reg_lock); } /* EOI to the PCI part... reenables interrupts */ @@ -1878,7 +1794,6 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id) static void snd_cs4281_opl3_command(struct snd_opl3 *opl3, unsigned short cmd, unsigned char val) { - unsigned long flags; struct cs4281 *chip = opl3->private_data; void __iomem *port; @@ -1887,19 +1802,17 @@ static void snd_cs4281_opl3_command(struct snd_opl3 *opl3, unsigned short cmd, else port = chip->ba0 + BA0_B0AP; /* left port */ - spin_lock_irqsave(&opl3->reg_lock, flags); + guard(spinlock_irqsave)(&opl3->reg_lock); writel((unsigned int)cmd, port); udelay(10); writel((unsigned int)val, port + 4); udelay(30); - - spin_unlock_irqrestore(&opl3->reg_lock, flags); } -static int snd_cs4281_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) +static int __snd_cs4281_probe(struct pci_dev *pci, + const struct pci_device_id *pci_id) { static int dev; struct snd_card *card; @@ -1914,69 +1827,61 @@ static int snd_cs4281_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, - 0, &card); + err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + sizeof(*chip), &card); if (err < 0) return err; + chip = card->private_data; - if ((err = snd_cs4281_create(card, pci, &chip, dual_codec[dev])) < 0) { - snd_card_free(card); + err = snd_cs4281_create(card, pci, dual_codec[dev]); + if (err < 0) return err; - } - card->private_data = chip; - if ((err = snd_cs4281_mixer(chip)) < 0) { - snd_card_free(card); + err = snd_cs4281_mixer(chip); + if (err < 0) return err; - } - if ((err = snd_cs4281_pcm(chip, 0)) < 0) { - snd_card_free(card); + err = snd_cs4281_pcm(chip, 0); + if (err < 0) return err; - } - if ((err = snd_cs4281_midi(chip, 0)) < 0) { - snd_card_free(card); + err = snd_cs4281_midi(chip, 0); + if (err < 0) return err; - } - if ((err = snd_opl3_new(card, OPL3_HW_OPL3_CS4281, &opl3)) < 0) { - snd_card_free(card); + err = snd_opl3_new(card, OPL3_HW_OPL3_CS4281, &opl3); + if (err < 0) return err; - } opl3->private_data = chip; opl3->command = snd_cs4281_opl3_command; snd_opl3_init(opl3); - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { - snd_card_free(card); + err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); + if (err < 0) return err; - } snd_cs4281_create_gameport(chip); - strcpy(card->driver, "CS4281"); - strcpy(card->shortname, "Cirrus Logic CS4281"); + strscpy(card->driver, "CS4281"); + strscpy(card->shortname, "Cirrus Logic CS4281"); sprintf(card->longname, "%s at 0x%lx, irq %d", card->shortname, chip->ba0_addr, chip->irq); - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); + err = snd_card_register(card); + if (err < 0) return err; - } pci_set_drvdata(pci, card); dev++; return 0; } -static void snd_cs4281_remove(struct pci_dev *pci) +static int snd_cs4281_probe(struct pci_dev *pci, + const struct pci_device_id *pci_id) { - snd_card_free(pci_get_drvdata(pci)); + return snd_card_free_on_error(&pci->dev, __snd_cs4281_probe(pci, pci_id)); } /* * Power Management */ -#ifdef CONFIG_PM_SLEEP - -static int saved_regs[SUSPEND_REGISTERS] = { +static const int saved_regs[SUSPEND_REGISTERS] = { BA0_JSCTL, BA0_GPIOR, BA0_SSCR, @@ -2002,8 +1907,6 @@ static int cs4281_suspend(struct device *dev) unsigned int i; snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - snd_ac97_suspend(chip->ac97); snd_ac97_suspend(chip->ac97_secondary); @@ -2066,19 +1969,14 @@ static int cs4281_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(cs4281_pm, cs4281_suspend, cs4281_resume); -#define CS4281_PM_OPS &cs4281_pm -#else -#define CS4281_PM_OPS NULL -#endif /* CONFIG_PM_SLEEP */ +static DEFINE_SIMPLE_DEV_PM_OPS(cs4281_pm, cs4281_suspend, cs4281_resume); static struct pci_driver cs4281_driver = { .name = KBUILD_MODNAME, .id_table = snd_cs4281_ids, .probe = snd_cs4281_probe, - .remove = snd_cs4281_remove, .driver = { - .pm = CS4281_PM_OPS, + .pm = &cs4281_pm, }, }; |
