Commit 79e8b218 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: emu10k1: Allocate resources with device-managed APIs

This patch converts the resource management in PCI emu10k1 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-34-tiwai@suse.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 9c211bf3
......@@ -1701,7 +1701,7 @@ struct snd_emu10k1 {
struct snd_dma_buffer silent_page; /* silent page */
struct snd_dma_buffer ptb_pages; /* page table pages */
struct snd_dma_device p16v_dma_dev;
struct snd_dma_buffer p16v_buffer;
struct snd_dma_buffer *p16v_buffer;
struct snd_util_memhdr *memhdr; /* page allocation list */
......@@ -1796,14 +1796,12 @@ int snd_emu10k1_create(struct snd_card *card,
unsigned short extout_mask,
long max_cache_bytes,
int enable_ir,
uint subsystem,
struct snd_emu10k1 ** remu);
uint subsystem);
int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device);
int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device);
int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device);
int snd_p16v_pcm(struct snd_emu10k1 *emu, int device);
int snd_p16v_free(struct snd_emu10k1 * emu);
int snd_p16v_mixer(struct snd_emu10k1 * emu);
int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device);
int snd_emu10k1_fx8010_pcm(struct snd_emu10k1 *emu, int device);
......
......@@ -99,67 +99,67 @@ static int snd_card_emu10k1_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(*emu), &card);
if (err < 0)
return err;
emu = card->private_data;
if (max_buffer_size[dev] < 32)
max_buffer_size[dev] = 32;
else if (max_buffer_size[dev] > 1024)
max_buffer_size[dev] = 1024;
err = snd_emu10k1_create(card, pci, extin[dev], extout[dev],
(long)max_buffer_size[dev] * 1024 * 1024,
enable_ir[dev], subsystem[dev],
&emu);
enable_ir[dev], subsystem[dev]);
if (err < 0)
goto error;
card->private_data = emu;
return err;
emu->delay_pcm_irq = delay_pcm_irq[dev] & 0x1f;
err = snd_emu10k1_pcm(emu, 0);
if (err < 0)
goto error;
return err;
err = snd_emu10k1_pcm_mic(emu, 1);
if (err < 0)
goto error;
return err;
err = snd_emu10k1_pcm_efx(emu, 2);
if (err < 0)
goto error;
return err;
/* This stores the periods table. */
if (emu->card_capabilities->ca0151_chip) { /* P16V */
err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
1024, &emu->p16v_buffer);
if (err < 0)
goto error;
emu->p16v_buffer =
snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, 1024);
if (!emu->p16v_buffer)
return -ENOMEM;
}
err = snd_emu10k1_mixer(emu, 0, 3);
if (err < 0)
goto error;
return err;
err = snd_emu10k1_timer(emu, 0);
if (err < 0)
goto error;
return err;
err = snd_emu10k1_pcm_multi(emu, 3);
if (err < 0)
goto error;
return err;
if (emu->card_capabilities->ca0151_chip) { /* P16V */
err = snd_p16v_pcm(emu, 4);
if (err < 0)
goto error;
return err;
}
if (emu->audigy) {
err = snd_emu10k1_audigy_midi(emu);
if (err < 0)
goto error;
return err;
} else {
err = snd_emu10k1_midi(emu);
if (err < 0)
goto error;
return err;
}
err = snd_emu10k1_fx8010_new(emu, 0);
if (err < 0)
goto error;
return err;
#ifdef ENABLE_SYNTH
if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH,
sizeof(struct snd_emu10k1_synth_arg), &wave) < 0 ||
......@@ -187,7 +187,7 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
err = snd_card_register(card);
if (err < 0)
goto error;
return err;
if (emu->card_capabilities->emu_model)
schedule_delayed_work(&emu->emu1010.firmware_work, 0);
......@@ -195,18 +195,8 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
pci_set_drvdata(pci, card);
dev++;
return 0;
error:
snd_card_free(card);
return err;
}
static void snd_card_emu10k1_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
}
#ifdef CONFIG_PM_SLEEP
static int snd_emu10k1_suspend(struct device *dev)
{
......@@ -263,7 +253,6 @@ static struct pci_driver emu10k1_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_emu10k1_ids,
.probe = snd_card_emu10k1_probe,
.remove = snd_card_emu10k1_remove,
.driver = {
.pm = SND_EMU10K1_PM_OPS,
},
......
......@@ -1242,8 +1242,10 @@ static int alloc_pm_buffer(struct snd_emu10k1 *emu);
static void free_pm_buffer(struct snd_emu10k1 *emu);
#endif
static int snd_emu10k1_free(struct snd_emu10k1 *emu)
static void snd_emu10k1_free(struct snd_card *card)
{
struct snd_emu10k1 *emu = card->private_data;
if (emu->port) { /* avoid access to already used hardware */
snd_emu10k1_fx8010_tram_setup(emu, 0);
snd_emu10k1_done(emu);
......@@ -1256,8 +1258,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
cancel_delayed_work_sync(&emu->emu1010.firmware_work);
release_firmware(emu->firmware);
release_firmware(emu->dock_fw);
if (emu->irq >= 0)
free_irq(emu->irq, emu);
snd_util_memhdr_free(emu->memhdr);
if (emu->silent_page.area)
snd_dma_free_pages(&emu->silent_page);
......@@ -1268,19 +1268,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
#ifdef CONFIG_PM_SLEEP
free_pm_buffer(emu);
#endif
if (emu->port)
pci_release_regions(emu->pci);
if (emu->card_capabilities->ca0151_chip) /* P16V */
snd_p16v_free(emu);
pci_disable_device(emu->pci);
kfree(emu);
return 0;
}
static int snd_emu10k1_dev_free(struct snd_device *device)
{
struct snd_emu10k1 *emu = device->device_data;
return snd_emu10k1_free(emu);
}
static const struct snd_emu_chip_details emu_chip_details[] = {
......@@ -1782,32 +1769,22 @@ int snd_emu10k1_create(struct snd_card *card,
unsigned short extout_mask,
long max_cache_bytes,
int enable_ir,
uint subsystem,
struct snd_emu10k1 **remu)
uint subsystem)
{
struct snd_emu10k1 *emu;
struct snd_emu10k1 *emu = card->private_data;
int idx, err;
int is_audigy;
size_t page_table_size;
__le32 *pgtbl;
unsigned int silent_page;
const struct snd_emu_chip_details *c;
static const struct snd_device_ops ops = {
.dev_free = snd_emu10k1_dev_free,
};
*remu = NULL;
/* enable PCI device */
err = pci_enable_device(pci);
err = pcim_enable_device(pci);
if (err < 0)
return err;
emu = kzalloc(sizeof(*emu), GFP_KERNEL);
if (emu == NULL) {
pci_disable_device(pci);
return -ENOMEM;
}
card->private_free = snd_emu10k1_free;
emu->card = card;
spin_lock_init(&emu->reg_lock);
spin_lock_init(&emu->emu_lock);
......@@ -1850,8 +1827,6 @@ int snd_emu10k1_create(struct snd_card *card,
}
if (c->vendor == 0) {
dev_err(card->dev, "emu10k1: Card not recognised\n");
kfree(emu);
pci_disable_device(pci);
return -ENOENT;
}
emu->card_capabilities = c;
......@@ -1883,8 +1858,6 @@ int snd_emu10k1_create(struct snd_card *card,
dev_err(card->dev,
"architecture does not support PCI busmaster DMA with mask 0x%lx\n",
emu->dma_mask);
kfree(emu);
pci_disable_device(pci);
return -ENXIO;
}
if (is_audigy)
......@@ -1893,11 +1866,8 @@ int snd_emu10k1_create(struct snd_card *card,
emu->gpr_base = FXGPREGBASE;
err = pci_request_regions(pci, "EMU10K1");
if (err < 0) {
kfree(emu);
pci_disable_device(pci);
if (err < 0)
return err;
}
emu->port = pci_resource_start(pci, 0);
emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT;
......@@ -1905,10 +1875,8 @@ int snd_emu10k1_create(struct snd_card *card,
page_table_size = sizeof(u32) * (emu->address_mode ? MAXPAGES1 :
MAXPAGES0);
if (snd_emu10k1_alloc_pages_maybe_wider(emu, page_table_size,
&emu->ptb_pages) < 0) {
err = -ENOMEM;
goto error;
}
&emu->ptb_pages) < 0)
return -ENOMEM;
dev_dbg(card->dev, "page table address range is %.8lx:%.8lx\n",
(unsigned long)emu->ptb_pages.addr,
(unsigned long)(emu->ptb_pages.addr + emu->ptb_pages.bytes));
......@@ -1917,26 +1885,20 @@ int snd_emu10k1_create(struct snd_card *card,
emu->max_cache_pages));
emu->page_addr_table = vmalloc(array_size(sizeof(unsigned long),
emu->max_cache_pages));
if (emu->page_ptr_table == NULL || emu->page_addr_table == NULL) {
err = -ENOMEM;
goto error;
}
if (!emu->page_ptr_table || !emu->page_addr_table)
return -ENOMEM;
if (snd_emu10k1_alloc_pages_maybe_wider(emu, EMUPAGESIZE,
&emu->silent_page) < 0) {
err = -ENOMEM;
goto error;
}
&emu->silent_page) < 0)
return -ENOMEM;
dev_dbg(card->dev, "silent page range is %.8lx:%.8lx\n",
(unsigned long)emu->silent_page.addr,
(unsigned long)(emu->silent_page.addr +
emu->silent_page.bytes));
emu->memhdr = snd_util_memhdr_new(emu->max_cache_pages * PAGE_SIZE);
if (emu->memhdr == NULL) {
err = -ENOMEM;
goto error;
}
if (!emu->memhdr)
return -ENOMEM;
emu->memhdr->block_extra_size = sizeof(struct snd_emu10k1_memblk) -
sizeof(struct snd_util_memblk);
......@@ -1954,18 +1916,16 @@ int snd_emu10k1_create(struct snd_card *card,
if (emu->card_capabilities->ca_cardbus_chip) {
err = snd_emu10k1_cardbus_init(emu);
if (err < 0)
goto error;
return err;
}
if (emu->card_capabilities->ecard) {
err = snd_emu10k1_ecard_init(emu);
if (err < 0)
goto error;
return err;
} else if (emu->card_capabilities->emu_model) {
err = snd_emu10k1_emu1010_init(emu);
if (err < 0) {
snd_emu10k1_free(emu);
if (err < 0)
return err;
}
} else {
/* 5.1: Enable the additional AC97 Slots. If the emu10k1 version
does not support this, it shouldn't do any harm */
......@@ -1979,11 +1939,9 @@ int snd_emu10k1_create(struct snd_card *card,
emu->fx8010.etram_pages.bytes = 0;
/* irq handler must be registered after I/O ports are activated */
if (request_irq(pci->irq, snd_emu10k1_interrupt, IRQF_SHARED,
KBUILD_MODNAME, emu)) {
err = -EBUSY;
goto error;
}
if (devm_request_irq(&pci->dev, pci->irq, snd_emu10k1_interrupt,
IRQF_SHARED, KBUILD_MODNAME, emu))
return -EBUSY;
emu->irq = pci->irq;
card->sync_irq = emu->irq;
......@@ -2022,33 +1980,23 @@ int snd_emu10k1_create(struct snd_card *card,
err = snd_emu10k1_init(emu, enable_ir, 0);
if (err < 0)
goto error;
return err;
#ifdef CONFIG_PM_SLEEP
err = alloc_pm_buffer(emu);
if (err < 0)
goto error;
return err;
#endif
/* Initialize the effect engine */
err = snd_emu10k1_init_efx(emu);
if (err < 0)
goto error;
return err;
snd_emu10k1_audio_enable(emu);
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, emu, &ops);
if (err < 0)
goto error;
#ifdef CONFIG_SND_PROC_FS
snd_emu10k1_proc_init(emu);
#endif
*remu = emu;
return 0;
error:
snd_emu10k1_free(emu);
return err;
}
#ifdef CONFIG_PM_SLEEP
......
......@@ -290,7 +290,7 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
int channel = substream->pcm->device - emu->p16v_device_offset;
u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel));
u32 *table_base = (u32 *)(emu->p16v_buffer->area+(8*16*channel));
u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
int i;
u32 tmp;
......@@ -308,8 +308,8 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
runtime->dma_addr, runtime->dma_area, table_base);
dev_dbg(emu->card->dev,
"dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",
emu->p16v_buffer.addr, emu->p16v_buffer.area,
emu->p16v_buffer.bytes);
emu->p16v_buffer->addr, emu->p16v_buffer->area,
emu->p16v_buffer->bytes);
#endif /* debug */
tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
switch (runtime->rate) {
......@@ -333,7 +333,7 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
table_base[(i*2)+1]=period_size_bytes<<16;
}
snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer.addr+(8*16*channel));
snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer->addr+(8*16*channel));
snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0);
snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
......@@ -567,20 +567,6 @@ static const struct snd_pcm_ops snd_p16v_capture_ops = {
.pointer = snd_p16v_pcm_pointer_capture,
};
int snd_p16v_free(struct snd_emu10k1 *chip)
{
// release the data
if (chip->p16v_buffer.area) {
snd_dma_free_pages(&chip->p16v_buffer);
/*
dev_dbg(chip->card->dev, "period lables free: %p\n",
&chip->p16v_buffer);
*/
}
return 0;
}
int snd_p16v_pcm(struct snd_emu10k1 *emu, int device)
{
struct snd_pcm *pcm;
......
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