diff options
Diffstat (limited to 'sound/pci/maestro3.c')
| -rw-r--r-- | sound/pci/maestro3.c | 347 |
1 files changed, 126 insertions, 221 deletions
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index d5417360f51f..3353980d5cd8 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Driver for ESS Maestro3/Allegro (ES1988) soundcards. * Copyright (c) 2000 by Zach Brown <zab@zabbo.net> @@ -6,32 +7,16 @@ * Most of the hardware init stuffs are based on maestro3 driver for * OSS/Free by Zach Brown. Many thanks to Zach! * - * 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 - * - * * ChangeLog: * Aug. 27, 2001 * - Fixed deadlock on capture * - Added Canyon3D-2 support by Rob Riggs <rob@pangalactic.org> - * */ #define CARD_NAME "ESS Maestro3/Allegro/Canyon3D-2" #define DRIVER_NAME "Maestro3" -#include <asm/io.h> +#include <linux/io.h> #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/init.h> @@ -54,11 +39,6 @@ MODULE_AUTHOR("Zach Brown <zab@zabbo.net>, Takashi Iwai <tiwai@suse.de>"); MODULE_DESCRIPTION("ESS Maestro3 PCI"); MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ESS,Maestro3 PCI}," - "{ESS,ES1988}," - "{ESS,Allegro PCI}," - "{ESS,Allegro-1 PCI}," - "{ESS,Canyon3D-2/LE PCI}}"); MODULE_FIRMWARE("ess/maestro3_assp_kernel.fw"); MODULE_FIRMWARE("ess/maestro3_assp_minisrc.fw"); @@ -789,9 +769,7 @@ struct snd_m3 { unsigned int in_suspend; -#ifdef CONFIG_PM_SLEEP u16 *suspend_mem; -#endif const struct firmware *assp_kernel_image; const struct firmware *assp_minisrc_image; @@ -800,7 +778,7 @@ struct snd_m3 { /* * pci ids */ -static DEFINE_PCI_DEVICE_TABLE(snd_m3_ids) = { +static const struct pci_device_id snd_m3_ids[] = { {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO_1, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO, PCI_ANY_ID, PCI_ANY_ID, @@ -822,7 +800,7 @@ static DEFINE_PCI_DEVICE_TABLE(snd_m3_ids) = { MODULE_DEVICE_TABLE(pci, snd_m3_ids); -static struct snd_pci_quirk m3_amp_quirk_list[] = { +static const struct snd_pci_quirk m3_amp_quirk_list[] = { SND_PCI_QUIRK(0x0E11, 0x0094, "Compaq Evo N600c", 0x0c), SND_PCI_QUIRK(0x10f7, 0x833e, "Panasonic CF-28", 0x0d), SND_PCI_QUIRK(0x10f7, 0x833d, "Panasonic CF-72", 0x0d), @@ -831,7 +809,7 @@ static struct snd_pci_quirk m3_amp_quirk_list[] = { { } /* END */ }; -static struct snd_pci_quirk m3_irda_quirk_list[] = { +static const struct snd_pci_quirk m3_irda_quirk_list[] = { SND_PCI_QUIRK(0x1028, 0x00b0, "Dell Inspiron 4000", 1), SND_PCI_QUIRK(0x1028, 0x00a4, "Dell Inspiron 8000", 1), SND_PCI_QUIRK(0x1028, 0x00e6, "Dell Inspiron 8100", 1), @@ -839,7 +817,7 @@ static struct snd_pci_quirk m3_irda_quirk_list[] = { }; /* hardware volume quirks */ -static struct snd_pci_quirk m3_hv_quirk_list[] = { +static const struct snd_pci_quirk m3_hv_quirk_list[] = { /* Allegro chips */ SND_PCI_QUIRK(0x0E11, 0x002E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), SND_PCI_QUIRK(0x0E11, 0x0094, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), @@ -917,7 +895,7 @@ static struct snd_pci_quirk m3_hv_quirk_list[] = { }; /* HP Omnibook quirks */ -static struct snd_pci_quirk m3_omnibook_quirk_list[] = { +static const struct snd_pci_quirk m3_omnibook_quirk_list[] = { SND_PCI_QUIRK_ID(0x103c, 0x0010), /* HP OmniBook 6000 */ SND_PCI_QUIRK_ID(0x103c, 0x0011), /* HP OmniBook 500 */ { } /* END */ @@ -1118,7 +1096,7 @@ snd_m3_pcm_trigger(struct snd_pcm_substream *subs, int cmd) if (snd_BUG_ON(!s)) return -ENXIO; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: @@ -1139,7 +1117,6 @@ snd_m3_pcm_trigger(struct snd_pcm_substream *subs, int cmd) } break; } - spin_unlock(&chip->reg_lock); return err; } @@ -1260,7 +1237,7 @@ static void snd_m3_pcm_setup2(struct snd_m3 *chip, struct m3_dma *s, snd_pcm_format_width(runtime->format) == 16 ? 0 : 1); /* set up dac/adc rate */ - freq = ((runtime->rate << 15) + 24000 ) / 48000; + freq = DIV_ROUND_CLOSEST(runtime->rate << 15, 48000); if (freq) freq--; @@ -1396,14 +1373,11 @@ static int snd_m3_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct m3_dma *s = substream->runtime->private_data; - int err; - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; /* set buffer address */ s->buffer_addr = substream->runtime->dma_addr; if (s->buffer_addr & 0x3) { - snd_printk(KERN_ERR "oh my, not aligned\n"); + dev_err(substream->pcm->card->dev, "oh my, not aligned\n"); s->buffer_addr = s->buffer_addr & ~0x3; } return 0; @@ -1416,7 +1390,6 @@ static int snd_m3_pcm_hw_free(struct snd_pcm_substream *substream) if (substream->runtime->private_data == NULL) return 0; s = substream->runtime->private_data; - snd_pcm_lib_free_pages(substream); s->buffer_addr = 0; return 0; } @@ -1438,7 +1411,7 @@ snd_m3_pcm_prepare(struct snd_pcm_substream *subs) runtime->rate < 8000) return -EINVAL; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); snd_m3_pcm_setup1(chip, s, subs); @@ -1449,8 +1422,6 @@ snd_m3_pcm_prepare(struct snd_pcm_substream *subs) snd_m3_pcm_setup2(chip, s, runtime); - spin_unlock_irq(&chip->reg_lock); - return 0; } @@ -1492,9 +1463,8 @@ snd_m3_pcm_pointer(struct snd_pcm_substream *subs) if (snd_BUG_ON(!s)) return 0; - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); ptr = snd_m3_get_pointer(chip, s, subs); - spin_unlock(&chip->reg_lock); return bytes_to_frames(subs->runtime, ptr); } @@ -1655,13 +1625,12 @@ static irqreturn_t snd_m3_interrupt(int irq, void *dev_id) if (ctl & DSP2HOST_REQ_TIMER) { outb(DSP2HOST_REQ_TIMER, chip->iobase + ASSP_HOST_INT_STATUS); /* update adc/dac info if it was a timer int */ - spin_lock(&chip->reg_lock); + guard(spinlock)(&chip->reg_lock); for (i = 0; i < chip->num_substreams; i++) { struct m3_dma *s = &chip->substreams[i]; if (s->running) snd_m3_update_ptr(chip, s); } - spin_unlock(&chip->reg_lock); } } } @@ -1681,7 +1650,7 @@ static irqreturn_t snd_m3_interrupt(int irq, void *dev_id) /* */ -static struct snd_pcm_hardware snd_m3_playback = +static const struct snd_pcm_hardware snd_m3_playback = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | @@ -1702,7 +1671,7 @@ static struct snd_pcm_hardware snd_m3_playback = .periods_max = 1024, }; -static struct snd_pcm_hardware snd_m3_capture = +static const struct snd_pcm_hardware snd_m3_capture = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | @@ -1733,18 +1702,16 @@ snd_m3_substream_open(struct snd_m3 *chip, struct snd_pcm_substream *subs) int i; struct m3_dma *s; - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); for (i = 0; i < chip->num_substreams; i++) { s = &chip->substreams[i]; if (! s->opened) goto __found; } - spin_unlock_irq(&chip->reg_lock); return -ENOMEM; __found: s->opened = 1; s->running = 0; - spin_unlock_irq(&chip->reg_lock); subs->runtime->private_data = s; s->substream = subs; @@ -1768,7 +1735,7 @@ snd_m3_substream_close(struct snd_m3 *chip, struct snd_pcm_substream *subs) if (s == NULL) return; /* not opened properly */ - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); if (s->substream && s->running) snd_m3_pcm_stop(chip, s, s->substream); /* does this happen? */ if (s->in_lists) { @@ -1779,7 +1746,6 @@ snd_m3_substream_close(struct snd_m3 *chip, struct snd_pcm_substream *subs) } s->running = 0; s->opened = 0; - spin_unlock_irq(&chip->reg_lock); } static int @@ -1789,7 +1755,8 @@ snd_m3_playback_open(struct snd_pcm_substream *subs) struct snd_pcm_runtime *runtime = subs->runtime; int err; - if ((err = snd_m3_substream_open(chip, subs)) < 0) + err = snd_m3_substream_open(chip, subs); + if (err < 0) return err; runtime->hw = snd_m3_playback; @@ -1813,7 +1780,8 @@ snd_m3_capture_open(struct snd_pcm_substream *subs) struct snd_pcm_runtime *runtime = subs->runtime; int err; - if ((err = snd_m3_substream_open(chip, subs)) < 0) + err = snd_m3_substream_open(chip, subs); + if (err < 0) return err; runtime->hw = snd_m3_capture; @@ -1834,10 +1802,9 @@ snd_m3_capture_close(struct snd_pcm_substream *subs) * create pcm instance */ -static struct snd_pcm_ops snd_m3_playback_ops = { +static const struct snd_pcm_ops snd_m3_playback_ops = { .open = snd_m3_playback_open, .close = snd_m3_playback_close, - .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_m3_pcm_hw_params, .hw_free = snd_m3_pcm_hw_free, .prepare = snd_m3_pcm_prepare, @@ -1845,10 +1812,9 @@ static struct snd_pcm_ops snd_m3_playback_ops = { .pointer = snd_m3_pcm_pointer, }; -static struct snd_pcm_ops snd_m3_capture_ops = { +static const struct snd_pcm_ops snd_m3_capture_ops = { .open = snd_m3_capture_open, .close = snd_m3_capture_close, - .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_m3_pcm_hw_params, .hw_free = snd_m3_pcm_hw_free, .prepare = snd_m3_pcm_prepare, @@ -1872,11 +1838,11 @@ snd_m3_pcm(struct snd_m3 * chip, int device) pcm->private_data = chip; pcm->info_flags = 0; - strcpy(pcm->name, chip->card->driver); + strscpy(pcm->name, chip->card->driver); chip->pcm = pcm; - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), 64*1024, 64*1024); + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, + &chip->pci->dev, 64*1024, 64*1024); return 0; } @@ -1900,7 +1866,7 @@ static int snd_m3_ac97_wait(struct snd_m3 *chip) cpu_relax(); } while (i-- > 0); - snd_printk(KERN_ERR "ac97 serial bus busy\n"); + dev_err(chip->card->dev, "ac97 serial bus busy\n"); return 1; } @@ -1929,15 +1895,32 @@ snd_m3_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) return; snd_m3_outw(chip, val, CODEC_DATA); snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND); + /* + * Workaround for buggy ES1988 integrated AC'97 codec. It remains silent + * until the MASTER volume or mute is touched (alsactl restore does not + * work). + */ + if (ac97->id == 0x45838308 && reg == AC97_MASTER) { + snd_m3_ac97_wait(chip); + snd_m3_outw(chip, val, CODEC_DATA); + snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND); + } } -static void snd_m3_remote_codec_config(int io, int isremote) +static void snd_m3_remote_codec_config(struct snd_m3 *chip, int isremote) { + int io = chip->iobase; + u16 tmp; + isremote = isremote ? 1 : 0; - outw((inw(io + RING_BUS_CTRL_B) & ~SECOND_CODEC_ID_MASK) | isremote, - io + RING_BUS_CTRL_B); + tmp = inw(io + RING_BUS_CTRL_B) & ~SECOND_CODEC_ID_MASK; + /* enable dock on Dell Latitude C810 */ + if (chip->pci->subsystem_vendor == 0x1028 && + chip->pci->subsystem_device == 0x00e5) + tmp |= M3I_DOCK_ENABLE; + outw(tmp | isremote, io + RING_BUS_CTRL_B); outw((inw(io + SDO_OUT_DEST_CTRL) & ~COMMAND_ADDR_OUT) | isremote, io + SDO_OUT_DEST_CTRL); outw((inw(io + SDO_IN_DEST_CTRL) & ~STATUS_ADDR_IN) | isremote, @@ -1989,7 +1972,7 @@ static void snd_m3_ac97_reset(struct snd_m3 *chip) if (!chip->irda_workaround) dir |= 0x10; /* assuming pci bus master? */ - snd_m3_remote_codec_config(io, 0); + snd_m3_remote_codec_config(chip, 0); outw(IO_SRAM_ENABLE, io + RING_BUS_CTRL_A); udelay(20); @@ -2015,7 +1998,8 @@ static void snd_m3_ac97_reset(struct snd_m3 *chip) delay1 += 10; delay2 += 100; - snd_printd("maestro3: retrying codec reset with delays of %d and %d ms\n", + dev_dbg(chip->card->dev, + "retrying codec reset with delays of %d and %d ms\n", delay1, delay2); } @@ -2035,21 +2019,20 @@ static int snd_m3_mixer(struct snd_m3 *chip) { struct snd_ac97_bus *pbus; struct snd_ac97_template ac97; -#ifndef CONFIG_SND_MAESTRO3_INPUT - struct snd_ctl_elem_id elem_id; -#endif int err; - static struct snd_ac97_bus_ops ops = { + static const struct snd_ac97_bus_ops ops = { .write = snd_m3_ac97_write, .read = snd_m3_ac97_read, }; - if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0) + err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus); + if (err < 0) return err; memset(&ac97, 0, sizeof(ac97)); ac97.private_data = chip; - if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97)) < 0) + err = snd_ac97_mixer(pbus, &ac97, &chip->ac97); + if (err < 0) return err; /* seems ac97 PCM needs initialization.. hack hack.. */ @@ -2058,14 +2041,10 @@ static int snd_m3_mixer(struct snd_m3 *chip) snd_ac97_write(chip->ac97, AC97_PCM, 0); #ifndef CONFIG_SND_MAESTRO3_INPUT - memset(&elem_id, 0, sizeof(elem_id)); - elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(elem_id.name, "Master Playback Switch"); - chip->master_switch = snd_ctl_find_id(chip->card, &elem_id); - memset(&elem_id, 0, sizeof(elem_id)); - elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(elem_id.name, "Master Playback Volume"); - chip->master_volume = snd_ctl_find_id(chip->card, &elem_id); + chip->master_switch = snd_ctl_find_id_mixer(chip->card, + "Master Playback Switch"); + chip->master_volume = snd_ctl_find_id_mixer(chip->card, + "Master Playback Volume"); #endif return 0; @@ -2085,7 +2064,7 @@ static const u16 minisrc_lpf[MINISRC_LPF_LEN] = { static void snd_m3_assp_init(struct snd_m3 *chip) { unsigned int i; - const u16 *data; + const __le16 *data; /* zero kernel data */ for (i = 0; i < (REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA) / 2; i++) @@ -2103,7 +2082,7 @@ static void snd_m3_assp_init(struct snd_m3 *chip) KDATA_DMA_XFER0); /* write kernel into code memory.. */ - data = (const u16 *)chip->assp_kernel_image->data; + data = (const __le16 *)chip->assp_kernel_image->data; for (i = 0 ; i * 2 < chip->assp_kernel_image->size; i++) { snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, REV_B_CODE_MEMORY_BEGIN + i, @@ -2116,7 +2095,7 @@ static void snd_m3_assp_init(struct snd_m3 *chip) * drop it there. It seems that the minisrc doesn't * need vectors, so we won't bother with them.. */ - data = (const u16 *)chip->assp_minisrc_image->data; + data = (const __le16 *)chip->assp_minisrc_image->data; for (i = 0; i * 2 < chip->assp_minisrc_image->size; i++) { snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, 0x400 + i, le16_to_cpu(data[i])); @@ -2194,7 +2173,8 @@ static int snd_m3_assp_client_init(struct snd_m3 *chip, struct m3_dma *s, int in address = 0x1100 + ((data_bytes/2) * index); if ((address + (data_bytes/2)) >= 0x1c00) { - snd_printk(KERN_ERR "no memory for %d bytes at ind %d (addr 0x%x)\n", + dev_err(chip->card->dev, + "no memory for %d bytes at ind %d (addr 0x%x)\n", data_bytes, index, address); return -ENOMEM; } @@ -2342,58 +2322,38 @@ snd_m3_enable_ints(struct snd_m3 *chip) /* */ -static int snd_m3_free(struct snd_m3 *chip) +static void snd_m3_free(struct snd_card *card) { + struct snd_m3 *chip = card->private_data; struct m3_dma *s; int i; cancel_work_sync(&chip->hwvol_work); -#ifdef CONFIG_SND_MAESTRO3_INPUT - if (chip->input_dev) - input_unregister_device(chip->input_dev); -#endif if (chip->substreams) { - spin_lock_irq(&chip->reg_lock); + guard(spinlock_irq)(&chip->reg_lock); for (i = 0; i < chip->num_substreams; i++) { s = &chip->substreams[i]; /* check surviving pcms; this should not happen though.. */ if (s->substream && s->running) snd_m3_pcm_stop(chip, s, s->substream); } - spin_unlock_irq(&chip->reg_lock); - kfree(chip->substreams); } if (chip->iobase) { outw(0, chip->iobase + HOST_INT_CTRL); /* disable ints */ } -#ifdef CONFIG_PM_SLEEP vfree(chip->suspend_mem); -#endif - - if (chip->irq >= 0) - free_irq(chip->irq, chip); - - if (chip->iobase) - pci_release_regions(chip->pci); - release_firmware(chip->assp_kernel_image); release_firmware(chip->assp_minisrc_image); - - pci_disable_device(chip->pci); - kfree(chip); - return 0; } /* * APM support */ -#ifdef CONFIG_PM_SLEEP static int m3_suspend(struct device *dev) { - struct pci_dev *pci = to_pci_dev(dev); struct snd_card *card = dev_get_drvdata(dev); struct snd_m3 *chip = card->private_data; int i, dsp_index; @@ -2404,7 +2364,6 @@ static int m3_suspend(struct device *dev) chip->in_suspend = 1; cancel_work_sync(&chip->hwvol_work); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); snd_ac97_suspend(chip->ac97); msleep(10); /* give the assp a chance to idle.. */ @@ -2419,16 +2378,11 @@ static int m3_suspend(struct device *dev) for (i = REV_B_DATA_MEMORY_BEGIN ; i <= REV_B_DATA_MEMORY_END; i++) chip->suspend_mem[dsp_index++] = snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA, i); - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, PCI_D3hot); return 0; } static int m3_resume(struct device *dev) { - struct pci_dev *pci = to_pci_dev(dev); struct snd_card *card = dev_get_drvdata(dev); struct snd_m3 *chip = card->private_data; int i, dsp_index; @@ -2436,16 +2390,6 @@ static int m3_resume(struct device *dev) if (chip->suspend_mem == NULL) return 0; - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "maestor3: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - /* first lets just bring everything back. .*/ snd_m3_outw(chip, 0, 0x54); snd_m3_outw(chip, 0, 0x56); @@ -2481,11 +2425,7 @@ static int m3_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(m3_pm, m3_suspend, m3_resume); -#define M3_PM_OPS &m3_pm -#else -#define M3_PM_OPS NULL -#endif /* CONFIG_PM_SLEEP */ +static DEFINE_SIMPLE_DEV_PM_OPS(m3_pm, m3_suspend, m3_resume); #ifdef CONFIG_SND_MAESTRO3_INPUT static int snd_m3_input_register(struct snd_m3 *chip) @@ -2493,7 +2433,7 @@ static int snd_m3_input_register(struct snd_m3 *chip) struct input_dev *input_dev; int err; - input_dev = input_allocate_device(); + input_dev = devm_input_allocate_device(&chip->pci->dev); if (!input_dev) return -ENOMEM; @@ -2513,10 +2453,8 @@ static int snd_m3_input_register(struct snd_m3 *chip) __set_bit(KEY_VOLUMEUP, input_dev->keybit); err = input_register_device(input_dev); - if (err) { - input_free_device(input_dev); + if (err) return err; - } chip->input_dev = input_dev; return 0; @@ -2526,44 +2464,25 @@ static int snd_m3_input_register(struct snd_m3 *chip) /* */ -static int snd_m3_dev_free(struct snd_device *device) -{ - struct snd_m3 *chip = device->device_data; - return snd_m3_free(chip); -} - static int snd_m3_create(struct snd_card *card, struct pci_dev *pci, int enable_amp, - int amp_gpio, - struct snd_m3 **chip_ret) + int amp_gpio) { - struct snd_m3 *chip; + struct snd_m3 *chip = card->private_data; int i, err; const struct snd_pci_quirk *quirk; - static struct snd_device_ops ops = { - .dev_free = snd_m3_dev_free, - }; - *chip_ret = NULL; - - if (pci_enable_device(pci)) + if (pcim_enable_device(pci)) return -EIO; /* check, if we can restrict PCI DMA transfers to 28 bits */ - if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 || - pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) { - snd_printk(KERN_ERR "architecture does not support 28bit PCI busmaster DMA\n"); - pci_disable_device(pci); + if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) { + dev_err(card->dev, + "architecture does not support 28bit PCI busmaster DMA\n"); return -ENXIO; } - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - spin_lock_init(&chip->reg_lock); switch (pci->device) { @@ -2579,6 +2498,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, chip->pci = pci; chip->irq = -1; INIT_WORK(&chip->hwvol_work, snd_m3_update_hw_volume); + card->private_free = snd_m3_free; chip->external_amp = enable_amp; if (amp_gpio >= 0 && amp_gpio <= 0x0f) @@ -2586,9 +2506,8 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, else { quirk = snd_pci_quirk_lookup(pci, m3_amp_quirk_list); if (quirk) { - snd_printdd(KERN_INFO - "maestro3: set amp-gpio for '%s'\n", - snd_pci_quirk_name(quirk)); + dev_info(card->dev, "set amp-gpio for '%s'\n", + snd_pci_quirk_name(quirk)); chip->amp_gpio = quirk->value; } else if (chip->allegro_flag) chip->amp_gpio = GPO_EXT_AMP_ALLEGRO; @@ -2598,9 +2517,8 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, quirk = snd_pci_quirk_lookup(pci, m3_irda_quirk_list); if (quirk) { - snd_printdd(KERN_INFO - "maestro3: enabled irda workaround for '%s'\n", - snd_pci_quirk_name(quirk)); + dev_info(card->dev, "enabled irda workaround for '%s'\n", + snd_pci_quirk_name(quirk)); chip->irda_workaround = 1; } quirk = snd_pci_quirk_lookup(pci, m3_hv_quirk_list); @@ -2610,32 +2528,25 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, chip->is_omnibook = 1; chip->num_substreams = NR_DSPS; - chip->substreams = kcalloc(chip->num_substreams, sizeof(struct m3_dma), - GFP_KERNEL); - if (chip->substreams == NULL) { - kfree(chip); - pci_disable_device(pci); + chip->substreams = devm_kcalloc(&pci->dev, chip->num_substreams, + sizeof(struct m3_dma), GFP_KERNEL); + if (!chip->substreams) return -ENOMEM; - } err = request_firmware(&chip->assp_kernel_image, "ess/maestro3_assp_kernel.fw", &pci->dev); - if (err < 0) { - snd_m3_free(chip); + if (err < 0) return err; - } err = request_firmware(&chip->assp_minisrc_image, "ess/maestro3_assp_minisrc.fw", &pci->dev); - if (err < 0) { - snd_m3_free(chip); + if (err < 0) return err; - } - if ((err = pci_request_regions(pci, card->driver)) < 0) { - snd_m3_free(chip); + err = pcim_request_all_regions(pci, card->driver); + if (err < 0) return err; - } + chip->iobase = pci_resource_start(pci, 0); /* just to be sure */ @@ -2650,60 +2561,58 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, snd_m3_hv_init(chip); - if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_m3_free(chip); + if (devm_request_irq(&pci->dev, pci->irq, snd_m3_interrupt, IRQF_SHARED, + KBUILD_MODNAME, chip)) { + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); return -ENOMEM; } chip->irq = pci->irq; - -#ifdef CONFIG_PM_SLEEP - chip->suspend_mem = vmalloc(sizeof(u16) * (REV_B_CODE_MEMORY_LENGTH + REV_B_DATA_MEMORY_LENGTH)); - if (chip->suspend_mem == NULL) - snd_printk(KERN_WARNING "can't allocate apm buffer\n"); -#endif - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_m3_free(chip); - return err; + card->sync_irq = chip->irq; + + if (IS_ENABLED(CONFIG_PM_SLEEP)) { + chip->suspend_mem = + vmalloc_array(REV_B_CODE_MEMORY_LENGTH + + REV_B_DATA_MEMORY_LENGTH, + sizeof(u16)); + if (!chip->suspend_mem) + dev_warn(card->dev, "can't allocate apm buffer\n"); } - if ((err = snd_m3_mixer(chip)) < 0) + err = snd_m3_mixer(chip); + if (err < 0) return err; for (i = 0; i < chip->num_substreams; i++) { struct m3_dma *s = &chip->substreams[i]; - if ((err = snd_m3_assp_client_init(chip, s, i)) < 0) + err = snd_m3_assp_client_init(chip, s, i); + if (err < 0) return err; } - if ((err = snd_m3_pcm(chip, 0)) < 0) + err = snd_m3_pcm(chip, 0); + if (err < 0) return err; #ifdef CONFIG_SND_MAESTRO3_INPUT if (chip->hv_config & HV_CTRL_ENABLE) { err = snd_m3_input_register(chip); if (err) - snd_printk(KERN_WARNING "Input device registration " - "failed with error %i", err); + dev_warn(card->dev, + "Input device registration failed with error %i", + err); } #endif snd_m3_enable_ints(chip); snd_m3_assp_continue(chip); - snd_card_set_dev(card, &pci->dev); - - *chip_ret = chip; - return 0; } /* */ static int -snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) +__snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { static int dev; struct snd_card *card; @@ -2721,41 +2630,37 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return -ENOENT; } - err = snd_card_create(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; switch (pci->device) { case PCI_DEVICE_ID_ESS_ALLEGRO: case PCI_DEVICE_ID_ESS_ALLEGRO_1: - strcpy(card->driver, "Allegro"); + strscpy(card->driver, "Allegro"); break; case PCI_DEVICE_ID_ESS_CANYON3D_2LE: case PCI_DEVICE_ID_ESS_CANYON3D_2: - strcpy(card->driver, "Canyon3D-2"); + strscpy(card->driver, "Canyon3D-2"); break; default: - strcpy(card->driver, "Maestro3"); + strscpy(card->driver, "Maestro3"); break; } - if ((err = snd_m3_create(card, pci, - external_amp[dev], - amp_gpio[dev], - &chip)) < 0) { - snd_card_free(card); + err = snd_m3_create(card, pci, external_amp[dev], amp_gpio[dev]); + if (err < 0) return err; - } - card->private_data = chip; sprintf(card->shortname, "ESS %s PCI", card->driver); sprintf(card->longname, "%s at 0x%lx, irq %d", card->shortname, chip->iobase, chip->irq); - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); + err = snd_card_register(card); + if (err < 0) return err; - } #if 0 /* TODO: not supported yet */ /* TODO enable MIDI IRQ and I/O */ @@ -2764,7 +2669,7 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK, -1, &chip->rmidi); if (err < 0) - printk(KERN_WARNING "maestro3: no MIDI support.\n"); + dev_warn(card->dev, "no MIDI support.\n"); #endif pci_set_drvdata(pci, card); @@ -2772,18 +2677,18 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return 0; } -static void snd_m3_remove(struct pci_dev *pci) +static int +snd_m3_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_m3_probe(pci, pci_id)); } static struct pci_driver m3_driver = { .name = KBUILD_MODNAME, .id_table = snd_m3_ids, .probe = snd_m3_probe, - .remove = snd_m3_remove, .driver = { - .pm = M3_PM_OPS, + .pm = &m3_pm, }, }; |
