Commit 2b377c6b authored by Takashi Iwai's avatar Takashi Iwai

ALSA: emu10k1x: Allocate resources with device-managed APIs

This patch converts the resource management in PCI emu10k1x driver
with devres as a clean up.  Each manual resource management is
converted with the corresponding devres helper, the page allocations
are done with the devres helper, and the card object release is
managed now via card->private_free instead of a lowlevel snd_device.

This should give no user-visible functional changes.

Link: https://lore.kernel.org/r/20210715075941.23332-35-tiwai@suse.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 79e8b218
...@@ -216,7 +216,6 @@ struct emu10k1x { ...@@ -216,7 +216,6 @@ struct emu10k1x {
struct pci_dev *pci; struct pci_dev *pci;
unsigned long port; unsigned long port;
struct resource *res_port;
int irq; int irq;
unsigned char revision; /* chip revision */ unsigned char revision; /* chip revision */
...@@ -233,7 +232,7 @@ struct emu10k1x { ...@@ -233,7 +232,7 @@ struct emu10k1x {
struct emu10k1x_voice capture_voice; struct emu10k1x_voice capture_voice;
u32 spdif_bits[3]; // SPDIF out setup u32 spdif_bits[3]; // SPDIF out setup
struct snd_dma_buffer dma_buffer; struct snd_dma_buffer *dma_buffer;
struct emu10k1x_midi midi; struct emu10k1x_midi midi;
}; };
...@@ -442,7 +441,7 @@ static int snd_emu10k1x_pcm_prepare(struct snd_pcm_substream *substream) ...@@ -442,7 +441,7 @@ static int snd_emu10k1x_pcm_prepare(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
struct emu10k1x_pcm *epcm = runtime->private_data; struct emu10k1x_pcm *epcm = runtime->private_data;
int voice = epcm->voice->number; int voice = epcm->voice->number;
u32 *table_base = (u32 *)(emu->dma_buffer.area+1024*voice); u32 *table_base = (u32 *)(emu->dma_buffer->area+1024*voice);
u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size); u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
int i; int i;
...@@ -451,7 +450,7 @@ static int snd_emu10k1x_pcm_prepare(struct snd_pcm_substream *substream) ...@@ -451,7 +450,7 @@ static int snd_emu10k1x_pcm_prepare(struct snd_pcm_substream *substream)
*table_base++=period_size_bytes<<16; *table_base++=period_size_bytes<<16;
} }
snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_ADDR, voice, emu->dma_buffer.addr+1024*voice); snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_ADDR, voice, emu->dma_buffer->addr+1024*voice);
snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_SIZE, voice, (runtime->periods - 1) << 19); snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_SIZE, voice, (runtime->periods - 1) << 19);
snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_PTR, voice, 0); snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_PTR, voice, 0);
snd_emu10k1x_ptr_write(emu, PLAYBACK_POINTER, voice, 0); snd_emu10k1x_ptr_write(emu, PLAYBACK_POINTER, voice, 0);
...@@ -737,37 +736,15 @@ static int snd_emu10k1x_ac97(struct emu10k1x *chip) ...@@ -737,37 +736,15 @@ static int snd_emu10k1x_ac97(struct emu10k1x *chip)
return snd_ac97_mixer(pbus, &ac97, &chip->ac97); return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
} }
static int snd_emu10k1x_free(struct emu10k1x *chip) static void snd_emu10k1x_free(struct snd_card *card)
{ {
struct emu10k1x *chip = card->private_data;
snd_emu10k1x_ptr_write(chip, TRIGGER_CHANNEL, 0, 0); snd_emu10k1x_ptr_write(chip, TRIGGER_CHANNEL, 0, 0);
// disable interrupts // disable interrupts
outl(0, chip->port + INTE); outl(0, chip->port + INTE);
// disable audio // disable audio
outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG); outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);
/* release the irq */
if (chip->irq >= 0)
free_irq(chip->irq, chip);
// release the i/o port
release_and_free_resource(chip->res_port);
// release the DMA
if (chip->dma_buffer.area) {
snd_dma_free_pages(&chip->dma_buffer);
}
pci_disable_device(chip->pci);
// release the data
kfree(chip);
return 0;
}
static int snd_emu10k1x_dev_free(struct snd_device *device)
{
struct emu10k1x *chip = device->device_data;
return snd_emu10k1x_free(chip);
} }
static irqreturn_t snd_emu10k1x_interrupt(int irq, void *dev_id) static irqreturn_t snd_emu10k1x_interrupt(int irq, void *dev_id)
...@@ -885,34 +862,21 @@ static int snd_emu10k1x_pcm(struct emu10k1x *emu, int device) ...@@ -885,34 +862,21 @@ static int snd_emu10k1x_pcm(struct emu10k1x *emu, int device)
} }
static int snd_emu10k1x_create(struct snd_card *card, static int snd_emu10k1x_create(struct snd_card *card,
struct pci_dev *pci, struct pci_dev *pci)
struct emu10k1x **rchip)
{ {
struct emu10k1x *chip; struct emu10k1x *chip = card->private_data;
int err; int err;
int ch; int ch;
static const struct snd_device_ops ops = {
.dev_free = snd_emu10k1x_dev_free,
};
*rchip = NULL;
err = pci_enable_device(pci); err = pcim_enable_device(pci);
if (err < 0) if (err < 0)
return err; return err;
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28)) < 0) { if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28)) < 0) {
dev_err(card->dev, "error to set 28bit mask DMA\n"); dev_err(card->dev, "error to set 28bit mask DMA\n");
pci_disable_device(pci);
return -ENXIO; return -ENXIO;
} }
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
}
chip->card = card; chip->card = card;
chip->pci = pci; chip->pci = pci;
chip->irq = -1; chip->irq = -1;
...@@ -920,29 +884,24 @@ static int snd_emu10k1x_create(struct snd_card *card, ...@@ -920,29 +884,24 @@ static int snd_emu10k1x_create(struct snd_card *card,
spin_lock_init(&chip->emu_lock); spin_lock_init(&chip->emu_lock);
spin_lock_init(&chip->voice_lock); spin_lock_init(&chip->voice_lock);
err = pci_request_regions(pci, "EMU10K1X");
if (err < 0)
return err;
chip->port = pci_resource_start(pci, 0); chip->port = pci_resource_start(pci, 0);
chip->res_port = request_region(chip->port, 8, "EMU10K1X");
if (!chip->res_port) {
dev_err(card->dev, "cannot allocate the port 0x%lx\n",
chip->port);
snd_emu10k1x_free(chip);
return -EBUSY;
}
if (request_irq(pci->irq, snd_emu10k1x_interrupt, if (devm_request_irq(&pci->dev, pci->irq, snd_emu10k1x_interrupt,
IRQF_SHARED, KBUILD_MODNAME, chip)) { IRQF_SHARED, KBUILD_MODNAME, chip)) {
dev_err(card->dev, "cannot grab irq %d\n", pci->irq); dev_err(card->dev, "cannot grab irq %d\n", pci->irq);
snd_emu10k1x_free(chip);
return -EBUSY; return -EBUSY;
} }
chip->irq = pci->irq; chip->irq = pci->irq;
card->sync_irq = chip->irq; card->sync_irq = chip->irq;
card->private_free = snd_emu10k1x_free;
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, chip->dma_buffer = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV,
4 * 1024, &chip->dma_buffer) < 0) { 4 * 1024);
snd_emu10k1x_free(chip); if (!chip->dma_buffer)
return -ENOMEM; return -ENOMEM;
}
pci_set_master(pci); pci_set_master(pci);
/* read revision & serial */ /* read revision & serial */
...@@ -998,12 +957,6 @@ static int snd_emu10k1x_create(struct snd_card *card, ...@@ -998,12 +957,6 @@ static int snd_emu10k1x_create(struct snd_card *card,
outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG); outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG);
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
if (err < 0) {
snd_emu10k1x_free(chip);
return err;
}
*rchip = chip;
return 0; return 0;
} }
...@@ -1553,50 +1506,37 @@ static int snd_emu10k1x_probe(struct pci_dev *pci, ...@@ -1553,50 +1506,37 @@ static int snd_emu10k1x_probe(struct pci_dev *pci,
return -ENOENT; return -ENOENT;
} }
err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
0, &card); sizeof(*chip), &card);
if (err < 0) if (err < 0)
return err; return err;
chip = card->private_data;
err = snd_emu10k1x_create(card, pci, &chip); err = snd_emu10k1x_create(card, pci);
if (err < 0) { if (err < 0)
snd_card_free(card);
return err; return err;
}
err = snd_emu10k1x_pcm(chip, 0); err = snd_emu10k1x_pcm(chip, 0);
if (err < 0) { if (err < 0)
snd_card_free(card);
return err; return err;
}
err = snd_emu10k1x_pcm(chip, 1); err = snd_emu10k1x_pcm(chip, 1);
if (err < 0) { if (err < 0)
snd_card_free(card);
return err; return err;
}
err = snd_emu10k1x_pcm(chip, 2); err = snd_emu10k1x_pcm(chip, 2);
if (err < 0) { if (err < 0)
snd_card_free(card);
return err; return err;
}
err = snd_emu10k1x_ac97(chip); err = snd_emu10k1x_ac97(chip);
if (err < 0) { if (err < 0)
snd_card_free(card);
return err; return err;
}
err = snd_emu10k1x_mixer(chip); err = snd_emu10k1x_mixer(chip);
if (err < 0) { if (err < 0)
snd_card_free(card);
return err; return err;
}
err = snd_emu10k1x_midi(chip); err = snd_emu10k1x_midi(chip);
if (err < 0) { if (err < 0)
snd_card_free(card);
return err; return err;
}
snd_emu10k1x_proc_init(chip); snd_emu10k1x_proc_init(chip);
...@@ -1606,21 +1546,14 @@ static int snd_emu10k1x_probe(struct pci_dev *pci, ...@@ -1606,21 +1546,14 @@ static int snd_emu10k1x_probe(struct pci_dev *pci,
card->shortname, chip->port, chip->irq); card->shortname, chip->port, chip->irq);
err = snd_card_register(card); err = snd_card_register(card);
if (err < 0) { if (err < 0)
snd_card_free(card);
return err; return err;
}
pci_set_drvdata(pci, card); pci_set_drvdata(pci, card);
dev++; dev++;
return 0; return 0;
} }
static void snd_emu10k1x_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
}
// PCI IDs // PCI IDs
static const struct pci_device_id snd_emu10k1x_ids[] = { static const struct pci_device_id snd_emu10k1x_ids[] = {
{ PCI_VDEVICE(CREATIVE, 0x0006), 0 }, /* Dell OEM version (EMU10K1) */ { PCI_VDEVICE(CREATIVE, 0x0006), 0 }, /* Dell OEM version (EMU10K1) */
...@@ -1633,7 +1566,6 @@ static struct pci_driver emu10k1x_driver = { ...@@ -1633,7 +1566,6 @@ static struct pci_driver emu10k1x_driver = {
.name = KBUILD_MODNAME, .name = KBUILD_MODNAME,
.id_table = snd_emu10k1x_ids, .id_table = snd_emu10k1x_ids,
.probe = snd_emu10k1x_probe, .probe = snd_emu10k1x_probe,
.remove = snd_emu10k1x_remove,
}; };
module_pci_driver(emu10k1x_driver); module_pci_driver(emu10k1x_driver);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment