diff options
Diffstat (limited to 'sound/pci/fm801.c')
| -rw-r--r-- | sound/pci/fm801.c | 315 |
1 files changed, 124 insertions, 191 deletions
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index e3fb9c61017c..4ca992449ea3 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -1,17 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * The driver for the ForteMedia FM801 based soundcards * 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. - * */ #include <linux/delay.h> @@ -36,8 +26,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); MODULE_DESCRIPTION("ForteMedia FM801"); MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ForteMedia,FM801}," - "{Genius,SoundMaker Live 5.1}}"); static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ @@ -154,6 +142,8 @@ MODULE_PARM_DESC(radio_nr, "Radio device numbers"); /** * struct fm801 - describes FM801 chip + * @dev: device for this chio + * @irq: irq number * @port: I/O port number * @multichannel: multichannel support * @secondary: secondary codec @@ -161,6 +151,31 @@ MODULE_PARM_DESC(radio_nr, "Radio device numbers"); * @tea575x_tuner: tuner access method & flags * @ply_ctrl: playback control * @cap_ctrl: capture control + * @ply_buffer: playback buffer + * @ply_buf: playback buffer index + * @ply_count: playback buffer count + * @ply_size: playback buffer size + * @ply_pos: playback position + * @cap_buffer: capture buffer + * @cap_buf: capture buffer index + * @cap_count: capture buffer count + * @cap_size: capture buffer size + * @cap_pos: capture position + * @ac97_bus: ac97 bus handle + * @ac97: ac97 handle + * @ac97_sec: ac97 secondary handle + * @card: ALSA card + * @pcm: PCM devices + * @rmidi: rmidi device + * @playback_substream: substream for playback + * @capture_substream: substream for capture + * @p_dma_size: playback DMA size + * @c_dma_size: capture DMA size + * @reg_lock: lock + * @proc_entry: /proc entry + * @v4l2_dev: v4l2 device + * @tea: tea575a structure + * @saved_regs: context saved during suspend */ struct fm801 { struct device *dev; @@ -207,9 +222,7 @@ struct fm801 { struct snd_tea575x tea; #endif -#ifdef CONFIG_PM_SLEEP u16 saved_regs[0x20]; -#endif }; /* @@ -266,16 +279,14 @@ static int snd_fm801_update_bits(struct fm801 *chip, unsigned short reg, unsigned short mask, unsigned short value) { int change; - unsigned long flags; unsigned short old, new; - spin_lock_irqsave(&chip->reg_lock, flags); + guard(spinlock_irqsave)(&chip->reg_lock); old = fm801_ioread16(chip, reg); new = (old & ~mask) | value; change = old != new; if (change) fm801_iowrite16(chip, reg, new); - spin_unlock_irqrestore(&chip->reg_lock, flags); return change; } @@ -380,7 +391,7 @@ static int snd_fm801_playback_trigger(struct snd_pcm_substream *substream, { struct fm801 *chip = snd_pcm_substream_chip(substream); - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: chip->ply_ctrl &= ~(FM801_BUF1_LAST | @@ -401,12 +412,10 @@ static int snd_fm801_playback_trigger(struct snd_pcm_substream *substream, chip->ply_ctrl &= ~FM801_PAUSE; break; default: - spin_unlock(&chip->reg_lock); snd_BUG(); return -EINVAL; } fm801_writew(chip, PLY_CTRL, chip->ply_ctrl); - spin_unlock(&chip->reg_lock); return 0; } @@ -415,7 +424,7 @@ static int snd_fm801_capture_trigger(struct snd_pcm_substream *substream, { struct fm801 *chip = snd_pcm_substream_chip(substream); - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: chip->cap_ctrl &= ~(FM801_BUF1_LAST | @@ -436,26 +445,13 @@ static int snd_fm801_capture_trigger(struct snd_pcm_substream *substream, chip->cap_ctrl &= ~FM801_PAUSE; break; default: - spin_unlock(&chip->reg_lock); snd_BUG(); return -EINVAL; } fm801_writew(chip, CAP_CTRL, chip->cap_ctrl); - spin_unlock(&chip->reg_lock); return 0; } -static int snd_fm801_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_fm801_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - static int snd_fm801_playback_prepare(struct snd_pcm_substream *substream) { struct fm801 *chip = snd_pcm_substream_chip(substream); @@ -463,7 +459,7 @@ static int snd_fm801_playback_prepare(struct snd_pcm_substream *substream) chip->ply_size = snd_pcm_lib_buffer_bytes(substream); chip->ply_count = snd_pcm_lib_period_bytes(substream); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); chip->ply_ctrl &= ~(FM801_START | FM801_16BIT | FM801_STEREO | FM801_RATE_MASK | FM801_CHANNELS_MASK); @@ -485,7 +481,6 @@ static int snd_fm801_playback_prepare(struct snd_pcm_substream *substream) fm801_writel(chip, PLY_BUF1, chip->ply_buffer); fm801_writel(chip, PLY_BUF2, chip->ply_buffer + (chip->ply_count % chip->ply_size)); - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -496,7 +491,7 @@ static int snd_fm801_capture_prepare(struct snd_pcm_substream *substream) chip->cap_size = snd_pcm_lib_buffer_bytes(substream); chip->cap_count = snd_pcm_lib_period_bytes(substream); - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); chip->cap_ctrl &= ~(FM801_START | FM801_16BIT | FM801_STEREO | FM801_RATE_MASK); if (snd_pcm_format_width(runtime->format) == 16) @@ -512,7 +507,6 @@ static int snd_fm801_capture_prepare(struct snd_pcm_substream *substream) fm801_writel(chip, CAP_BUF1, chip->cap_buffer); fm801_writel(chip, CAP_BUF2, chip->cap_buffer + (chip->cap_count % chip->cap_size)); - spin_unlock_irq(&chip->reg_lock); return 0; } @@ -523,13 +517,12 @@ static snd_pcm_uframes_t snd_fm801_playback_pointer(struct snd_pcm_substream *su if (!(chip->ply_ctrl & FM801_START)) return 0; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); ptr = chip->ply_pos + (chip->ply_count - 1) - fm801_readw(chip, PLY_COUNT); if (fm801_readw(chip, IRQ_STATUS) & FM801_IRQ_PLAYBACK) { ptr += chip->ply_count; ptr %= chip->ply_size; } - spin_unlock(&chip->reg_lock); return bytes_to_frames(substream->runtime, ptr); } @@ -540,13 +533,12 @@ static snd_pcm_uframes_t snd_fm801_capture_pointer(struct snd_pcm_substream *sub if (!(chip->cap_ctrl & FM801_START)) return 0; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); ptr = chip->cap_pos + (chip->cap_count - 1) - fm801_readw(chip, CAP_COUNT); if (fm801_readw(chip, IRQ_STATUS) & FM801_IRQ_CAPTURE) { ptr += chip->cap_count; ptr %= chip->cap_size; } - spin_unlock(&chip->reg_lock); return bytes_to_frames(substream->runtime, ptr); } @@ -563,31 +555,31 @@ static irqreturn_t snd_fm801_interrupt(int irq, void *dev_id) /* ack first */ fm801_writew(chip, IRQ_STATUS, status); if (chip->pcm && (status & FM801_IRQ_PLAYBACK) && chip->playback_substream) { - spin_lock(&chip->reg_lock); - chip->ply_buf++; - chip->ply_pos += chip->ply_count; - chip->ply_pos %= chip->ply_size; - tmp = chip->ply_pos + chip->ply_count; - tmp %= chip->ply_size; - if (chip->ply_buf & 1) - fm801_writel(chip, PLY_BUF1, chip->ply_buffer + tmp); - else - fm801_writel(chip, PLY_BUF2, chip->ply_buffer + tmp); - spin_unlock(&chip->reg_lock); + scoped_guard(spinlock, &chip->reg_lock) { + chip->ply_buf++; + chip->ply_pos += chip->ply_count; + chip->ply_pos %= chip->ply_size; + tmp = chip->ply_pos + chip->ply_count; + tmp %= chip->ply_size; + if (chip->ply_buf & 1) + fm801_writel(chip, PLY_BUF1, chip->ply_buffer + tmp); + else + fm801_writel(chip, PLY_BUF2, chip->ply_buffer + tmp); + } snd_pcm_period_elapsed(chip->playback_substream); } if (chip->pcm && (status & FM801_IRQ_CAPTURE) && chip->capture_substream) { - spin_lock(&chip->reg_lock); - chip->cap_buf++; - chip->cap_pos += chip->cap_count; - chip->cap_pos %= chip->cap_size; - tmp = chip->cap_pos + chip->cap_count; - tmp %= chip->cap_size; - if (chip->cap_buf & 1) - fm801_writel(chip, CAP_BUF1, chip->cap_buffer + tmp); - else - fm801_writel(chip, CAP_BUF2, chip->cap_buffer + tmp); - spin_unlock(&chip->reg_lock); + scoped_guard(spinlock, &chip->reg_lock) { + chip->cap_buf++; + chip->cap_pos += chip->cap_count; + chip->cap_pos %= chip->cap_size; + tmp = chip->cap_pos + chip->cap_count; + tmp %= chip->cap_size; + if (chip->cap_buf & 1) + fm801_writel(chip, CAP_BUF1, chip->cap_buffer + tmp); + else + fm801_writel(chip, CAP_BUF2, chip->cap_buffer + tmp); + } snd_pcm_period_elapsed(chip->capture_substream); } if (chip->rmidi && (status & FM801_IRQ_MPU)) @@ -655,7 +647,8 @@ static int snd_fm801_playback_open(struct snd_pcm_substream *substream) SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels); } - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; return 0; } @@ -670,7 +663,8 @@ static int snd_fm801_capture_open(struct snd_pcm_substream *substream) runtime->hw = snd_fm801_capture; snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; return 0; } @@ -694,9 +688,6 @@ static int snd_fm801_capture_close(struct snd_pcm_substream *substream) static const struct snd_pcm_ops snd_fm801_playback_ops = { .open = snd_fm801_playback_open, .close = snd_fm801_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_fm801_hw_params, - .hw_free = snd_fm801_hw_free, .prepare = snd_fm801_playback_prepare, .trigger = snd_fm801_playback_trigger, .pointer = snd_fm801_playback_pointer, @@ -705,9 +696,6 @@ static const struct snd_pcm_ops snd_fm801_playback_ops = { static const struct snd_pcm_ops snd_fm801_capture_ops = { .open = snd_fm801_capture_open, .close = snd_fm801_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_fm801_hw_params, - .hw_free = snd_fm801_hw_free, .prepare = snd_fm801_capture_prepare, .trigger = snd_fm801_capture_trigger, .pointer = snd_fm801_capture_pointer, @@ -719,7 +707,8 @@ static int snd_fm801_pcm(struct fm801 *chip, int device) struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(chip->card, "FM801", device, 1, 1, &pcm)) < 0) + err = snd_pcm_new(chip->card, "FM801", device, 1, 1, &pcm); + if (err < 0) return err; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_fm801_playback_ops); @@ -727,12 +716,11 @@ static int snd_fm801_pcm(struct fm801 *chip, int device) pcm->private_data = chip; pcm->info_flags = 0; - strcpy(pcm->name, "FM801"); + strscpy(pcm->name, "FM801"); chip->pcm = pcm; - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(pdev), - chip->multichannel ? 128*1024 : 64*1024, 128*1024); + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &pdev->dev, + chip->multichannel ? 128*1024 : 64*1024, 128*1024); return snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, snd_pcm_alt_chmaps, @@ -752,7 +740,7 @@ struct snd_fm801_tea575x_gpio { char *name; }; -static struct snd_fm801_tea575x_gpio snd_fm801_tea575x_gpios[] = { +static const struct snd_fm801_tea575x_gpio snd_fm801_tea575x_gpios[] = { { .data = 1, .clk = 3, .wren = 2, .most = 0, .name = "SF256-PCS" }, { .data = 1, .clk = 0, .wren = 2, .most = 3, .name = "SF256-PCP" }, { .data = 2, .clk = 0, .wren = 1, .most = 3, .name = "SF64-PCR" }, @@ -926,10 +914,9 @@ static int snd_fm801_get_double(struct snd_kcontrol *kcontrol, int invert = (kcontrol->private_value >> 24) & 0xff; long *value = ucontrol->value.integer.value; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); value[0] = (fm801_ioread16(chip, reg) >> shift_left) & mask; value[1] = (fm801_ioread16(chip, reg) >> shift_right) & mask; - spin_unlock_irq(&chip->reg_lock); if (invert) { value[0] = mask - value[0]; value[1] = mask - value[1]; @@ -988,7 +975,8 @@ static int snd_fm801_put_mux(struct snd_kcontrol *kcontrol, struct fm801 *chip = snd_kcontrol_chip(kcontrol); unsigned short val; - if ((val = ucontrol->value.enumerated.item[0]) > 4) + val = ucontrol->value.enumerated.item[0]; + if (val > 4) return -EINVAL; return snd_fm801_update_bits(chip, FM801_REC_SRC, 7, val); } @@ -997,7 +985,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_dsp, -3450, 150, 0); #define FM801_CONTROLS ARRAY_SIZE(snd_fm801_controls) -static struct snd_kcontrol_new snd_fm801_controls[] = { +static const struct snd_kcontrol_new snd_fm801_controls[] = { FM801_DOUBLE_TLV("Wave Playback Volume", FM801_PCM_VOL, 0, 8, 31, 1, db_scale_dsp), FM801_SINGLE("Wave Playback Switch", FM801_PCM_VOL, 15, 1, 1), @@ -1018,7 +1006,7 @@ FM801_SINGLE("FM Playback Switch", FM801_FM_VOL, 15, 1, 1), #define FM801_CONTROLS_MULTI ARRAY_SIZE(snd_fm801_controls_multi) -static struct snd_kcontrol_new snd_fm801_controls_multi[] = { +static const struct snd_kcontrol_new snd_fm801_controls_multi[] = { FM801_SINGLE("AC97 2ch->4ch Copy Switch", FM801_CODEC_CTRL, 7, 1, 0), FM801_SINGLE("AC97 18-bit Switch", FM801_CODEC_CTRL, 10, 1, 0), FM801_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), FM801_I2S_MODE, 8, 1, 0), @@ -1027,45 +1015,30 @@ FM801_SINGLE(SNDRV_CTL_NAME_IEC958("Raw Data ",CAPTURE,SWITCH), FM801_I2S_MODE, FM801_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), FM801_GEN_CTRL, 2, 1, 0), }; -static void snd_fm801_mixer_free_ac97_bus(struct snd_ac97_bus *bus) -{ - struct fm801 *chip = bus->private_data; - chip->ac97_bus = NULL; -} - -static void snd_fm801_mixer_free_ac97(struct snd_ac97 *ac97) -{ - struct fm801 *chip = ac97->private_data; - if (ac97->num == 0) { - chip->ac97 = NULL; - } else { - chip->ac97_sec = NULL; - } -} - static int snd_fm801_mixer(struct fm801 *chip) { struct snd_ac97_template ac97; unsigned int i; int err; - static struct snd_ac97_bus_ops ops = { + static const struct snd_ac97_bus_ops ops = { .write = snd_fm801_codec_write, .read = snd_fm801_codec_read, }; - if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0) + err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus); + if (err < 0) return err; - chip->ac97_bus->private_free = snd_fm801_mixer_free_ac97_bus; memset(&ac97, 0, sizeof(ac97)); ac97.private_data = chip; - ac97.private_free = snd_fm801_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->secondary) { ac97.num = 1; ac97.addr = chip->secondary_addr; - if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97_sec)) < 0) + err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97_sec); + if (err < 0) return err; } for (i = 0; i < FM801_CONTROLS; i++) { @@ -1173,60 +1146,42 @@ static void snd_fm801_chip_init(struct fm801 *chip) FM801_IRQ_PLAYBACK | FM801_IRQ_CAPTURE | FM801_IRQ_MPU); } -static int snd_fm801_free(struct fm801 *chip) +static void snd_fm801_free(struct snd_card *card) { + struct fm801 *chip = card->private_data; unsigned short cmdw; - if (chip->irq < 0) - goto __end_hw; - /* interrupt setup - mask everything */ cmdw = fm801_readw(chip, IRQ_MASK); cmdw |= 0x00c3; fm801_writew(chip, IRQ_MASK, cmdw); - devm_free_irq(chip->dev, chip->irq, chip); - - __end_hw: #ifdef CONFIG_SND_FM801_TEA575X_BOOL if (!(chip->tea575x_tuner & TUNER_DISABLED)) { snd_tea575x_exit(&chip->tea); v4l2_device_unregister(&chip->v4l2_dev); } #endif - return 0; -} - -static int snd_fm801_dev_free(struct snd_device *device) -{ - struct fm801 *chip = device->device_data; - return snd_fm801_free(chip); } static int snd_fm801_create(struct snd_card *card, struct pci_dev *pci, int tea575x_tuner, - int radio_nr, - struct fm801 **rchip) + int radio_nr) { - struct fm801 *chip; + struct fm801 *chip = card->private_data; int err; - static struct snd_device_ops ops = { - .dev_free = snd_fm801_dev_free, - }; - *rchip = NULL; - if ((err = pcim_enable_device(pci)) < 0) + err = pcim_enable_device(pci); + if (err < 0) return err; - chip = devm_kzalloc(&pci->dev, sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; spin_lock_init(&chip->reg_lock); chip->card = card; chip->dev = &pci->dev; chip->irq = -1; chip->tea575x_tuner = tea575x_tuner; - if ((err = pci_request_regions(pci, "FM801")) < 0) + err = pcim_request_all_regions(pci, "FM801"); + if (err < 0) return err; chip->port = pci_resource_start(pci, 0); @@ -1247,26 +1202,20 @@ static int snd_fm801_create(struct snd_card *card, if (devm_request_irq(&pci->dev, pci->irq, snd_fm801_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); - snd_fm801_free(chip); return -EBUSY; } chip->irq = pci->irq; + card->sync_irq = chip->irq; pci_set_master(pci); } + card->private_free = snd_fm801_free; snd_fm801_chip_init(chip); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_fm801_free(chip); - return err; - } - #ifdef CONFIG_SND_FM801_TEA575X_BOOL err = v4l2_device_register(&pci->dev, &chip->v4l2_dev); - if (err < 0) { - snd_fm801_free(chip); + if (err < 0) return err; - } chip->tea.v4l2_dev = &chip->v4l2_dev; chip->tea.radio_nr = radio_nr; chip->tea.private_data = chip; @@ -1276,7 +1225,6 @@ static int snd_fm801_create(struct snd_card *card, (chip->tea575x_tuner & TUNER_TYPE_MASK) < 4) { if (snd_tea575x_init(&chip->tea, THIS_MODULE)) { dev_err(card->dev, "TEA575x radio not found\n"); - snd_fm801_free(chip); return -ENODEV; } } else if ((chip->tea575x_tuner & TUNER_TYPE_MASK) == 0) { @@ -1300,17 +1248,15 @@ static int snd_fm801_create(struct snd_card *card, chip->tea575x_tuner |= tuner_only; } if (!(chip->tea575x_tuner & TUNER_DISABLED)) { - strlcpy(chip->tea.card, get_tea575x_gpio(chip)->name, + strscpy(chip->tea.card, get_tea575x_gpio(chip)->name, sizeof(chip->tea.card)); } #endif - - *rchip = chip; return 0; } -static int snd_card_fm801_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) +static int __snd_card_fm801_probe(struct pci_dev *pci, + const struct pci_device_id *pci_id) { static int dev; struct snd_card *card; @@ -1325,18 +1271,17 @@ static int snd_card_fm801_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; - if ((err = snd_fm801_create(card, pci, tea575x_tuner[dev], radio_nr[dev], &chip)) < 0) { - snd_card_free(card); + chip = card->private_data; + err = snd_fm801_create(card, pci, tea575x_tuner[dev], radio_nr[dev]); + if (err < 0) return err; - } - card->private_data = chip; - strcpy(card->driver, "FM801"); - strcpy(card->shortname, "ForteMedia FM801-"); + strscpy(card->driver, "FM801"); + strscpy(card->shortname, "ForteMedia FM801-"); strcat(card->shortname, chip->multichannel ? "AU" : "AS"); sprintf(card->longname, "%s at 0x%lx, irq %i", card->shortname, chip->port, chip->irq); @@ -1344,50 +1289,44 @@ static int snd_card_fm801_probe(struct pci_dev *pci, if (chip->tea575x_tuner & TUNER_ONLY) goto __fm801_tuner_only; - if ((err = snd_fm801_pcm(chip, 0)) < 0) { - snd_card_free(card); + err = snd_fm801_pcm(chip, 0); + if (err < 0) return err; - } - if ((err = snd_fm801_mixer(chip)) < 0) { - snd_card_free(card); + err = snd_fm801_mixer(chip); + if (err < 0) return err; - } - if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_FM801, - chip->port + FM801_MPU401_DATA, - MPU401_INFO_INTEGRATED | - MPU401_INFO_IRQ_HOOK, - -1, &chip->rmidi)) < 0) { - snd_card_free(card); + err = snd_mpu401_uart_new(card, 0, MPU401_HW_FM801, + chip->port + FM801_MPU401_DATA, + MPU401_INFO_INTEGRATED | + MPU401_INFO_IRQ_HOOK, + -1, &chip->rmidi); + if (err < 0) return err; - } - if ((err = snd_opl3_create(card, chip->port + FM801_OPL3_BANK0, - chip->port + FM801_OPL3_BANK1, - OPL3_HW_OPL3_FM801, 1, &opl3)) < 0) { - snd_card_free(card); + err = snd_opl3_create(card, chip->port + FM801_OPL3_BANK0, + chip->port + FM801_OPL3_BANK1, + OPL3_HW_OPL3_FM801, 1, &opl3); + if (err < 0) return err; - } - 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; - } __fm801_tuner_only: - 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_card_fm801_remove(struct pci_dev *pci) +static int snd_card_fm801_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_card_fm801_probe(pci, pci_id)); } -#ifdef CONFIG_PM_SLEEP -static unsigned char saved_regs[] = { +static const unsigned char saved_regs[] = { FM801_PCM_VOL, FM801_I2S_VOL, FM801_FM_VOL, FM801_REC_SRC, FM801_PLY_CTRL, FM801_PLY_COUNT, FM801_PLY_BUF1, FM801_PLY_BUF2, FM801_CAP_CTRL, FM801_CAP_COUNT, FM801_CAP_BUF1, FM801_CAP_BUF2, @@ -1408,7 +1347,6 @@ static int snd_fm801_suspend(struct device *dev) if (chip->tea575x_tuner & TUNER_ONLY) { /* FIXME: tea575x suspend */ } else { - snd_pcm_suspend_all(chip->pcm); snd_ac97_suspend(chip->ac97); snd_ac97_suspend(chip->ac97_sec); } @@ -1444,19 +1382,14 @@ static int snd_fm801_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(snd_fm801_pm, snd_fm801_suspend, snd_fm801_resume); -#define SND_FM801_PM_OPS &snd_fm801_pm -#else -#define SND_FM801_PM_OPS NULL -#endif /* CONFIG_PM_SLEEP */ +static DEFINE_SIMPLE_DEV_PM_OPS(snd_fm801_pm, snd_fm801_suspend, snd_fm801_resume); static struct pci_driver fm801_driver = { .name = KBUILD_MODNAME, .id_table = snd_fm801_ids, .probe = snd_card_fm801_probe, - .remove = snd_card_fm801_remove, .driver = { - .pm = SND_FM801_PM_OPS, + .pm = &snd_fm801_pm, }, }; |
