diff options
Diffstat (limited to '')
-rw-r--r-- | sound/pci/fm801.c | 181 |
1 files changed, 80 insertions, 101 deletions
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 181ebafa550a..62b3cb126c6d 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -26,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 */ @@ -144,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 @@ -151,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; @@ -634,7 +659,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; } @@ -649,7 +675,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; } @@ -692,7 +719,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); @@ -960,7 +988,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); } @@ -999,22 +1028,6 @@ 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; @@ -1025,19 +1038,20 @@ static int snd_fm801_mixer(struct fm801 *chip) .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++) { @@ -1145,60 +1159,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 const 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 = pci_request_regions(pci, "FM801"); + if (err < 0) return err; chip->port = pci_resource_start(pci, 0); @@ -1219,7 +1215,6 @@ 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; @@ -1227,19 +1222,13 @@ static int snd_fm801_create(struct snd_card *card, 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; @@ -1249,7 +1238,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) { @@ -1273,17 +1261,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; @@ -1298,15 +1284,14 @@ 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-"); @@ -1317,46 +1302,41 @@ 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 @@ -1426,7 +1406,6 @@ 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, }, |