diff options
Diffstat (limited to 'sound/pci/via82xx_modem.c')
| -rw-r--r-- | sound/pci/via82xx_modem.c | 200 |
1 files changed, 68 insertions, 132 deletions
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index b13c8688cc8d..6ce2cd88cda6 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * ALSA modem driver for VIA VT82xx (South Bridge) * @@ -6,21 +7,6 @@ * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> * Tjeerd.Mulder <Tjeerd.Mulder@fujitsu-siemens.com> * 2002 Takashi Iwai <tiwai@suse.de> - * - * 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 - * */ /* @@ -52,7 +38,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); MODULE_DESCRIPTION("VIA VT82xx modem"); MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C modem,pci}}"); static int index = -2; /* Exclude the first card */ static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ @@ -281,12 +266,13 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre { unsigned int i, idx, ofs, rest; struct via82xx_modem *chip = snd_pcm_substream_chip(substream); + __le32 *pgtbl; if (dev->table.area == NULL) { /* the start of each lists must be aligned to 8 bytes, * but the kernel pages are much bigger, so we don't care */ - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), + if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &chip->pci->dev, PAGE_ALIGN(VIA_TABLE_SIZE * 2 * 8), &dev->table) < 0) return -ENOMEM; @@ -302,6 +288,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre /* fill the entries */ idx = 0; ofs = 0; + pgtbl = (__le32 *)dev->table.area; for (i = 0; i < periods; i++) { rest = fragsize; /* fill descriptors for a period. @@ -318,7 +305,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre return -EINVAL; } addr = snd_pcm_sgbuf_get_addr(substream, ofs); - ((u32 *)dev->table.area)[idx << 1] = cpu_to_le32(addr); + pgtbl[idx << 1] = cpu_to_le32(addr); r = PAGE_SIZE - (ofs % PAGE_SIZE); if (rest < r) r = rest; @@ -335,7 +322,7 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre "tbl %d: at %d size %d (rest %d)\n", idx, ofs, r, rest); */ - ((u32 *)dev->table.area)[(idx<<1) + 1] = cpu_to_le32(r | flag); + pgtbl[(idx<<1) + 1] = cpu_to_le32(r | flag); dev->idx_table[idx].offset = ofs; dev->idx_table[idx].size = r; ofs += r; @@ -382,7 +369,8 @@ static int snd_via82xx_codec_ready(struct via82xx_modem *chip, int secondary) while (timeout-- > 0) { udelay(1); - if (!((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)) + val = snd_via82xx_codec_xread(chip); + if (!(val & VIA_REG_AC97_BUSY)) return val & 0xffff; } dev_err(chip->card->dev, "codec_ready: codec %i is not ready [0x%x]\n", @@ -410,7 +398,7 @@ static int snd_via82xx_codec_valid(struct via82xx_modem *chip, int secondary) static void snd_via82xx_codec_wait(struct snd_ac97 *ac97) { struct via82xx_modem *chip = ac97->private_data; - int err; + __always_unused int err; err = snd_via82xx_codec_ready(chip, ac97->num); /* here we need to wait fairly for long time.. */ msleep(500); @@ -495,7 +483,7 @@ static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id) // _skip_sgd: /* check status for each stream */ - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); for (i = 0; i < chip->num_devs; i++) { struct viadev *viadev = &chip->devs[i]; unsigned char c_status = inb(VIADEV_REG(viadev, OFFSET_STATUS)); @@ -509,7 +497,6 @@ static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id) } outb(c_status, VIADEV_REG(viadev, OFFSET_STATUS)); /* ack */ } - spin_unlock(&chip->reg_lock); return IRQ_HANDLED; } @@ -628,7 +615,7 @@ static snd_pcm_uframes_t snd_via686_pcm_pointer(struct snd_pcm_substream *substr if (!(inb(VIADEV_REG(viadev, OFFSET_STATUS)) & VIA_REG_STAT_ACTIVE)) return 0; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); count = inl(VIADEV_REG(viadev, OFFSET_CURR_COUNT)) & 0xffffff; /* The via686a does not have the current index register, * so we need to calculate the index from CURR_PTR. @@ -640,7 +627,6 @@ static snd_pcm_uframes_t snd_via686_pcm_pointer(struct snd_pcm_substream *substr idx = ((ptr - (unsigned int)viadev->table.addr) / 8 - 1) % viadev->tbl_entries; res = calc_linear_pos(chip, viadev, idx, count); - spin_unlock(&chip->reg_lock); return bytes_to_frames(substream->runtime, res); } @@ -656,9 +642,6 @@ static int snd_via82xx_hw_params(struct snd_pcm_substream *substream, struct viadev *viadev = substream->runtime->private_data; int err; - err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - if (err < 0) - return err; err = build_via_table(viadev, substream, chip->pci, params_periods(hw_params), params_period_bytes(hw_params)); @@ -681,7 +664,6 @@ static int snd_via82xx_hw_free(struct snd_pcm_substream *substream) struct viadev *viadev = substream->runtime->private_data; clean_via_table(viadev, substream, chip->pci); - snd_pcm_lib_free_pages(substream); return 0; } @@ -755,13 +737,15 @@ static int snd_via82xx_modem_pcm_open(struct via82xx_modem *chip, struct viadev runtime->hw = snd_via82xx_hw; - if ((err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_rates)) < 0) + err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &hw_constraints_rates); + if (err < 0) return err; /* we may remove following constaint when we modify table entries in interrupt */ - 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; runtime->private_data = viadev; @@ -809,26 +793,22 @@ static int snd_via82xx_pcm_close(struct snd_pcm_substream *substream) static const struct snd_pcm_ops snd_via686_playback_ops = { .open = snd_via82xx_playback_open, .close = snd_via82xx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_via82xx_hw_params, .hw_free = snd_via82xx_hw_free, .prepare = snd_via82xx_pcm_prepare, .trigger = snd_via82xx_pcm_trigger, .pointer = snd_via686_pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, }; /* via686 capture callbacks */ static const struct snd_pcm_ops snd_via686_capture_ops = { .open = snd_via82xx_capture_open, .close = snd_via82xx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_via82xx_hw_params, .hw_free = snd_via82xx_hw_free, .prepare = snd_via82xx_pcm_prepare, .trigger = snd_via82xx_pcm_trigger, .pointer = snd_via686_pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, }; @@ -860,16 +840,13 @@ static int snd_via686_pcm_new(struct via82xx_modem *chip) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_via686_capture_ops); pcm->dev_class = SNDRV_PCM_CLASS_MODEM; pcm->private_data = chip; - strcpy(pcm->name, chip->card->shortname); + strscpy(pcm->name, chip->card->shortname); chip->pcms[0] = pcm; init_viadev(chip, 0, VIA_REG_MO_STATUS, 0); init_viadev(chip, 1, VIA_REG_MI_STATUS, 1); - if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(chip->pci), - 64*1024, 128*1024)) < 0) - return err; - + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG, + &chip->pci->dev, 64*1024, 128*1024); return 0; } @@ -896,13 +873,14 @@ static int snd_via82xx_mixer_new(struct via82xx_modem *chip) { struct snd_ac97_template ac97; int err; - static struct snd_ac97_bus_ops ops = { + static const struct snd_ac97_bus_ops ops = { .write = snd_via82xx_codec_write, .read = snd_via82xx_codec_read, .wait = snd_via82xx_codec_wait, }; - 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_via82xx_mixer_free_ac97_bus; chip->ac97_bus->clock = chip->ac97_clock; @@ -914,7 +892,8 @@ static int snd_via82xx_mixer_new(struct via82xx_modem *chip) ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE; ac97.num = chip->ac97_secondary; - 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; return 0; @@ -937,10 +916,8 @@ static void snd_via82xx_proc_read(struct snd_info_entry *entry, struct snd_info_ static void snd_via82xx_proc_init(struct via82xx_modem *chip) { - struct snd_info_entry *entry; - - if (! snd_card_proc_new(chip->card, "via82xx", &entry)) - snd_info_set_text_ops(entry, chip, snd_via82xx_proc_read); + snd_card_ro_proc_new(chip->card, "via82xx", chip, + snd_via82xx_proc_read); } /* @@ -997,7 +974,8 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip) schedule_timeout_uninterruptible(1); } while (time_before(jiffies, end_time)); - if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) + val = snd_via82xx_codec_xread(chip); + if (val & VIA_REG_AC97_BUSY) dev_err(chip->card->dev, "AC'97 codec is not ready [0x%x]\n", val); @@ -1009,7 +987,8 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip) VIA_REG_AC97_SECONDARY_VALID | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); do { - if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_SECONDARY_VALID) { + val = snd_via82xx_codec_xread(chip); + if (val & VIA_REG_AC97_SECONDARY_VALID) { chip->ac97_secondary = 1; goto __ac97_ok2; } @@ -1027,7 +1006,6 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip) return 0; } -#ifdef CONFIG_PM_SLEEP /* * power management */ @@ -1038,11 +1016,8 @@ static int snd_via82xx_suspend(struct device *dev) int i; snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - for (i = 0; i < 2; i++) - snd_pcm_suspend_all(chip->pcms[i]); for (i = 0; i < chip->num_devs; i++) snd_via82xx_channel_reset(chip, &chip->devs[i]); - synchronize_irq(chip->irq); snd_ac97_suspend(chip->ac97); return 0; } @@ -1064,102 +1039,65 @@ static int snd_via82xx_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(snd_via82xx_pm, snd_via82xx_suspend, snd_via82xx_resume); -#define SND_VIA82XX_PM_OPS &snd_via82xx_pm -#else -#define SND_VIA82XX_PM_OPS NULL -#endif /* CONFIG_PM_SLEEP */ +static DEFINE_SIMPLE_DEV_PM_OPS(snd_via82xx_pm, snd_via82xx_suspend, snd_via82xx_resume); -static int snd_via82xx_free(struct via82xx_modem *chip) +static void snd_via82xx_free(struct snd_card *card) { + struct via82xx_modem *chip = card->private_data; unsigned int i; - if (chip->irq < 0) - goto __end_hw; /* disable interrupts */ for (i = 0; i < chip->num_devs; i++) snd_via82xx_channel_reset(chip, &chip->devs[i]); - - __end_hw: - if (chip->irq >= 0) - free_irq(chip->irq, chip); - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - kfree(chip); - return 0; -} - -static int snd_via82xx_dev_free(struct snd_device *device) -{ - struct via82xx_modem *chip = device->device_data; - return snd_via82xx_free(chip); } static int snd_via82xx_create(struct snd_card *card, struct pci_dev *pci, int chip_type, int revision, - unsigned int ac97_clock, - struct via82xx_modem **r_via) + unsigned int ac97_clock) { - struct via82xx_modem *chip; + struct via82xx_modem *chip = card->private_data; int err; - static struct snd_device_ops ops = { - .dev_free = snd_via82xx_dev_free, - }; - if ((err = pci_enable_device(pci)) < 0) + err = pcim_enable_device(pci); + if (err < 0) return err; - if ((chip = kzalloc(sizeof(*chip), GFP_KERNEL)) == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - spin_lock_init(&chip->reg_lock); chip->card = card; chip->pci = pci; chip->irq = -1; - if ((err = pci_request_regions(pci, card->driver)) < 0) { - kfree(chip); - pci_disable_device(pci); + err = pcim_request_all_regions(pci, card->driver); + if (err < 0) return err; - } chip->port = pci_resource_start(pci, 0); - if (request_irq(pci->irq, snd_via82xx_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip)) { + if (devm_request_irq(&pci->dev, pci->irq, snd_via82xx_interrupt, + IRQF_SHARED, KBUILD_MODNAME, chip)) { dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); - snd_via82xx_free(chip); return -EBUSY; } chip->irq = pci->irq; + card->sync_irq = chip->irq; + card->private_free = snd_via82xx_free; if (ac97_clock >= 8000 && ac97_clock <= 48000) chip->ac97_clock = ac97_clock; - synchronize_irq(chip->irq); - if ((err = snd_via82xx_chip_init(chip)) < 0) { - snd_via82xx_free(chip); - return err; - } - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_via82xx_free(chip); + err = snd_via82xx_chip_init(chip); + if (err < 0) return err; - } /* The 8233 ac97 controller does not implement the master bit * in the pci command register. IMHO this is a violation of the PCI spec. * We call pci_set_master here because it does not hurt. */ pci_set_master(pci); - - *r_via = chip; return 0; } -static int snd_via82xx_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) +static int __snd_via82xx_probe(struct pci_dev *pci, + const struct pci_device_id *pci_id) { struct snd_card *card; struct via82xx_modem *chip; @@ -1167,31 +1105,34 @@ static int snd_via82xx_probe(struct pci_dev *pci, unsigned int i; int err; - err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card); + err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE, + sizeof(*chip), &card); if (err < 0) return err; + chip = card->private_data; card_type = pci_id->driver_data; switch (card_type) { case TYPE_CARD_VIA82XX_MODEM: - strcpy(card->driver, "VIA82XX-MODEM"); + strscpy(card->driver, "VIA82XX-MODEM"); sprintf(card->shortname, "VIA 82XX modem"); break; default: dev_err(card->dev, "invalid card type %d\n", card_type); - err = -EINVAL; - goto __error; + return -EINVAL; } - if ((err = snd_via82xx_create(card, pci, chip_type, pci->revision, - ac97_clock, &chip)) < 0) - goto __error; - card->private_data = chip; - if ((err = snd_via82xx_mixer_new(chip)) < 0) - goto __error; + err = snd_via82xx_create(card, pci, chip_type, pci->revision, + ac97_clock); + if (err < 0) + return err; + err = snd_via82xx_mixer_new(chip); + if (err < 0) + return err; - if ((err = snd_via686_pcm_new(chip)) < 0 ) - goto __error; + err = snd_via686_pcm_new(chip); + if (err < 0) + return err; /* disable interrupts */ for (i = 0; i < chip->num_devs; i++) @@ -1202,30 +1143,25 @@ static int snd_via82xx_probe(struct pci_dev *pci, snd_via82xx_proc_init(chip); - 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); return 0; - - __error: - snd_card_free(card); - return err; } -static void snd_via82xx_remove(struct pci_dev *pci) +static int snd_via82xx_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_via82xx_probe(pci, pci_id)); } static struct pci_driver via82xx_modem_driver = { .name = KBUILD_MODNAME, .id_table = snd_via82xx_modem_ids, .probe = snd_via82xx_probe, - .remove = snd_via82xx_remove, .driver = { - .pm = SND_VIA82XX_PM_OPS, + .pm = &snd_via82xx_pm, }, }; |
