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(*trident), &card);
if (err < 0)
return err;
+ trident = card->private_data;
err = snd_trident_create(card, pci,
pcm_channels[dev],
((pci->vendor << 16) | pci->device) == TRIDENT_DEVICE_ID_SI7018 ? 1 : 2,
- wavetable_size[dev],
- &trident);
- if (err < 0) {
- snd_card_free(card);
+ wavetable_size[dev]);
+ if (err < 0)
return err;
- }
- card->private_data = trident;
switch (trident->device) {
case TRIDENT_DEVICE_ID_DX:
card->shortname, trident->port, trident->irq);
err = snd_trident_pcm(trident, pcm_dev++);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
switch (trident->device) {
case TRIDENT_DEVICE_ID_DX:
case TRIDENT_DEVICE_ID_NX:
err = snd_trident_foldback_pcm(trident, pcm_dev++);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
break;
}
if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) {
err = snd_trident_spdif_pcm(trident, pcm_dev++);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
}
if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE,
MPU401_INFO_INTEGRATED |
MPU401_INFO_IRQ_HOOK,
-1, &trident->rmidi);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
}
snd_trident_create_gameport(trident);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
+ if (err < 0)
return err;
- }
pci_set_drvdata(pci, card);
dev++;
return 0;
}
-static void snd_trident_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
-}
-
static struct pci_driver trident_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_trident_ids,
.probe = snd_trident_probe,
- .remove = snd_trident_remove,
#ifdef CONFIG_PM_SLEEP
.driver = {
.pm = &snd_trident_pm,
static void snd_trident_clear_voices(struct snd_trident * trident,
unsigned short v_min, unsigned short v_max);
-static int snd_trident_free(struct snd_trident *trident);
+static void snd_trident_free(struct snd_card *card);
/*
* common I/O routines
snd_card_ro_proc_new(trident->card, s, trident, snd_trident_proc_read);
}
-static int snd_trident_dev_free(struct snd_device *device)
-{
- struct snd_trident *trident = device->device_data;
- return snd_trident_free(trident);
-}
-
/*---------------------------------------------------------------------------
snd_trident_tlb_alloc
/* TLB array must be aligned to 16kB !!! so we allocate
32kB region and correct offset when necessary */
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &trident->pci->dev,
- 2 * SNDRV_TRIDENT_MAX_PAGES * 4, &trident->tlb.buffer) < 0) {
+ trident->tlb.buffer =
+ snd_devm_alloc_pages(&trident->pci->dev, SNDRV_DMA_TYPE_DEV,
+ 2 * SNDRV_TRIDENT_MAX_PAGES * 4);
+ if (!trident->tlb.buffer) {
dev_err(trident->card->dev, "unable to allocate TLB buffer\n");
return -ENOMEM;
}
- trident->tlb.entries = (__le32 *)ALIGN((unsigned long)trident->tlb.buffer.area, SNDRV_TRIDENT_MAX_PAGES * 4);
- trident->tlb.entries_dmaaddr = ALIGN(trident->tlb.buffer.addr, SNDRV_TRIDENT_MAX_PAGES * 4);
+ trident->tlb.entries = (__le32 *)ALIGN((unsigned long)trident->tlb.buffer->area, SNDRV_TRIDENT_MAX_PAGES * 4);
+ trident->tlb.entries_dmaaddr = ALIGN(trident->tlb.buffer->addr, SNDRV_TRIDENT_MAX_PAGES * 4);
/* allocate and setup silent page and initialise TLB entries */
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &trident->pci->dev,
- SNDRV_TRIDENT_PAGE_SIZE, &trident->tlb.silent_page) < 0) {
+ trident->tlb.silent_page =
+ snd_devm_alloc_pages(&trident->pci->dev, SNDRV_DMA_TYPE_DEV,
+ SNDRV_TRIDENT_PAGE_SIZE);
+ if (!trident->tlb.silent_page) {
dev_err(trident->card->dev, "unable to allocate silent page\n");
return -ENOMEM;
}
- memset(trident->tlb.silent_page.area, 0, SNDRV_TRIDENT_PAGE_SIZE);
+ memset(trident->tlb.silent_page->area, 0, SNDRV_TRIDENT_PAGE_SIZE);
for (i = 0; i < SNDRV_TRIDENT_MAX_PAGES; i++)
- trident->tlb.entries[i] = cpu_to_le32(trident->tlb.silent_page.addr & ~(SNDRV_TRIDENT_PAGE_SIZE-1));
+ trident->tlb.entries[i] = cpu_to_le32(trident->tlb.silent_page->addr & ~(SNDRV_TRIDENT_PAGE_SIZE-1));
/* use emu memory block manager code to manage tlb page allocation */
trident->tlb.memhdr = snd_util_memhdr_new(SNDRV_TRIDENT_PAGE_SIZE * SNDRV_TRIDENT_MAX_PAGES);
struct pci_dev *pci,
int pcm_streams,
int pcm_spdif_device,
- int max_wavetable_size,
- struct snd_trident ** rtrident)
+ int max_wavetable_size)
{
- struct snd_trident *trident;
+ struct snd_trident *trident = card->private_data;
int i, err;
struct snd_trident_voice *voice;
struct snd_trident_pcm_mixer *tmix;
- static const struct snd_device_ops ops = {
- .dev_free = snd_trident_dev_free,
- };
-
- *rtrident = NULL;
/* enable PCI device */
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
/* check, if we can restrict PCI DMA transfers to 30 bits */
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(30))) {
dev_err(card->dev,
"architecture does not support 30bit PCI busmaster DMA\n");
- pci_disable_device(pci);
return -ENXIO;
}
- trident = kzalloc(sizeof(*trident), GFP_KERNEL);
- if (trident == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
trident->device = (pci->vendor << 16) | pci->device;
trident->card = card;
trident->pci = pci;
max_wavetable_size = 0;
trident->synth.max_size = max_wavetable_size * 1024;
trident->irq = -1;
+ card->private_free = snd_trident_free;
trident->midi_port = TRID_REG(trident, T4D_MPU401_BASE);
pci_set_master(pci);
err = pci_request_regions(pci, "Trident Audio");
- if (err < 0) {
- kfree(trident);
- pci_disable_device(pci);
+ if (err < 0)
return err;
- }
trident->port = pci_resource_start(pci, 0);
- if (request_irq(pci->irq, snd_trident_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, trident)) {
+ if (devm_request_irq(&pci->dev, pci->irq, snd_trident_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, trident)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
- snd_trident_free(trident);
return -EBUSY;
}
trident->irq = pci->irq;
/* allocate 16k-aligned TLB for NX cards */
trident->tlb.entries = NULL;
- trident->tlb.buffer.area = NULL;
if (trident->device == TRIDENT_DEVICE_ID_NX) {
err = snd_trident_tlb_alloc(trident);
- if (err < 0) {
- snd_trident_free(trident);
+ if (err < 0)
return err;
- }
}
trident->spdif_bits = trident->spdif_pcm_bits = SNDRV_PCM_DEFAULT_CON_SPDIF;
snd_BUG();
break;
}
- if (err < 0) {
- snd_trident_free(trident);
- return err;
- }
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, trident, &ops);
- if (err < 0) {
- snd_trident_free(trident);
+ if (err < 0)
return err;
- }
err = snd_trident_mixer(trident, pcm_spdif_device);
if (err < 0)
snd_trident_enable_eso(trident);
snd_trident_proc_init(trident);
- *rtrident = trident;
return 0;
}
Description: This routine will free the device specific class for
the 4DWave card.
- Parameters: trident - device specific private data for 4DWave card
+ Parameters: card - card to release
Returns: None.
---------------------------------------------------------------------------*/
-static int snd_trident_free(struct snd_trident *trident)
+static void snd_trident_free(struct snd_card *card)
{
+ struct snd_trident *trident = card->private_data;
+
snd_trident_free_gameport(trident);
snd_trident_disable_eso(trident);
// Disable S/PDIF out
else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
outl(0, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
}
- if (trident->irq >= 0)
- free_irq(trident->irq, trident);
- if (trident->tlb.buffer.area) {
+ if (trident->tlb.buffer) {
outl(0, TRID_REG(trident, NX_TLBC));
snd_util_memhdr_free(trident->tlb.memhdr);
- if (trident->tlb.silent_page.area)
- snd_dma_free_pages(&trident->tlb.silent_page);
- snd_dma_free_pages(&trident->tlb.buffer);
}
- pci_release_regions(trident->pci);
- pci_disable_device(trident->pci);
- kfree(trident);
- return 0;
}
/*---------------------------------------------------------------------------
/* fill TLB entrie(s) corresponding to page with ptr */
#define set_tlb_bus(trident,page,addr) __set_tlb_bus(trident,page,addr)
/* fill TLB entrie(s) corresponding to page with silence pointer */
-#define set_silent_tlb(trident,page) __set_tlb_bus(trident, page, trident->tlb.silent_page.addr)
+#define set_silent_tlb(trident,page) __set_tlb_bus(trident, page, trident->tlb.silent_page->addr)
/* get aligned page from offset address */
#define get_aligned_page(offset) ((offset) >> 12)
/* get offset address from aligned page */
static inline void set_silent_tlb(struct snd_trident *trident, int page)
{
page <<= 1;
- __set_tlb_bus(trident, page, trident->tlb.silent_page.addr);
- __set_tlb_bus(trident, page+1, trident->tlb.silent_page.addr);
+ __set_tlb_bus(trident, page, trident->tlb.silent_page->addr);
+ __set_tlb_bus(trident, page+1, trident->tlb.silent_page->addr);
}
#else
int i;
page *= UNIT_PAGES;
for (i = 0; i < UNIT_PAGES; i++, page++)
- __set_tlb_bus(trident, page, trident->tlb.silent_page.addr);
+ __set_tlb_bus(trident, page, trident->tlb.silent_page->addr);
}
#endif /* PAGE_SIZE */