Commit 5eba4c64 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: cs5535audio: Allocate resources with device-managed APIs

This patch converts the resource management in PCI cs5535audio driver
with devres as a clean up.  Each manual resource management is
converted with the corresponding devres helper, and the card object
release is managed now via card->private_free instead of a lowlevel
snd_device.  A slight uncertain change is the call of
olpc_quirks_cleanup() at removal: formerly this was called
unconditionally at remove, but this should be a conditionally call,
hence the machine_is_olpc() check is added here as well.

This should give no user-visible functional changes.

Link: https://lore.kernel.org/r/20210715075941.23332-32-tiwai@suse.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 5bff69b3
...@@ -237,51 +237,24 @@ static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id) ...@@ -237,51 +237,24 @@ static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int snd_cs5535audio_free(struct cs5535audio *cs5535au) static void snd_cs5535audio_free(struct snd_card *card)
{ {
pci_set_power_state(cs5535au->pci, PCI_D3hot); olpc_quirks_cleanup();
if (cs5535au->irq >= 0)
free_irq(cs5535au->irq, cs5535au);
pci_release_regions(cs5535au->pci);
pci_disable_device(cs5535au->pci);
kfree(cs5535au);
return 0;
}
static int snd_cs5535audio_dev_free(struct snd_device *device)
{
struct cs5535audio *cs5535au = device->device_data;
return snd_cs5535audio_free(cs5535au);
} }
static int snd_cs5535audio_create(struct snd_card *card, static int snd_cs5535audio_create(struct snd_card *card,
struct pci_dev *pci, struct pci_dev *pci)
struct cs5535audio **rcs5535au)
{ {
struct cs5535audio *cs5535au; struct cs5535audio *cs5535au = card->private_data;
int err; int err;
static const struct snd_device_ops ops = {
.dev_free = snd_cs5535audio_dev_free,
};
*rcs5535au = NULL; err = pcim_enable_device(pci);
err = pci_enable_device(pci);
if (err < 0) if (err < 0)
return err; return err;
if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) { if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
dev_warn(card->dev, "unable to get 32bit dma\n"); dev_warn(card->dev, "unable to get 32bit dma\n");
err = -ENXIO; return -ENXIO;
goto pcifail;
}
cs5535au = kzalloc(sizeof(*cs5535au), GFP_KERNEL);
if (cs5535au == NULL) {
err = -ENOMEM;
goto pcifail;
} }
spin_lock_init(&cs5535au->reg_lock); spin_lock_init(&cs5535au->reg_lock);
...@@ -290,38 +263,22 @@ static int snd_cs5535audio_create(struct snd_card *card, ...@@ -290,38 +263,22 @@ static int snd_cs5535audio_create(struct snd_card *card,
cs5535au->irq = -1; cs5535au->irq = -1;
err = pci_request_regions(pci, "CS5535 Audio"); err = pci_request_regions(pci, "CS5535 Audio");
if (err < 0) { if (err < 0)
kfree(cs5535au); return err;
goto pcifail;
}
cs5535au->port = pci_resource_start(pci, 0); cs5535au->port = pci_resource_start(pci, 0);
if (request_irq(pci->irq, snd_cs5535audio_interrupt, if (devm_request_irq(&pci->dev, pci->irq, snd_cs5535audio_interrupt,
IRQF_SHARED, KBUILD_MODNAME, cs5535au)) { IRQF_SHARED, KBUILD_MODNAME, cs5535au)) {
dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
err = -EBUSY; return -EBUSY;
goto sndfail;
} }
cs5535au->irq = pci->irq; cs5535au->irq = pci->irq;
card->sync_irq = cs5535au->irq; card->sync_irq = cs5535au->irq;
pci_set_master(pci); pci_set_master(pci);
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, cs5535au, &ops);
if (err < 0)
goto sndfail;
*rcs5535au = cs5535au;
return 0; return 0;
sndfail: /* leave the device alive, just kill the snd */
snd_cs5535audio_free(cs5535au);
return err;
pcifail:
pci_disable_device(pci);
return err;
} }
static int snd_cs5535audio_probe(struct pci_dev *pci, static int snd_cs5535audio_probe(struct pci_dev *pci,
...@@ -339,24 +296,24 @@ static int snd_cs5535audio_probe(struct pci_dev *pci, ...@@ -339,24 +296,24 @@ static int snd_cs5535audio_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(*cs5535au), &card);
if (err < 0) if (err < 0)
return err; return err;
cs5535au = card->private_data;
card->private_free = snd_cs5535audio_free;
err = snd_cs5535audio_create(card, pci, &cs5535au); err = snd_cs5535audio_create(card, pci);
if (err < 0) if (err < 0)
goto probefail_out; return err;
card->private_data = cs5535au;
err = snd_cs5535audio_mixer(cs5535au); err = snd_cs5535audio_mixer(cs5535au);
if (err < 0) if (err < 0)
goto probefail_out; return err;
err = snd_cs5535audio_pcm(cs5535au); err = snd_cs5535audio_pcm(cs5535au);
if (err < 0) if (err < 0)
goto probefail_out; return err;
strcpy(card->driver, DRIVER_NAME); strcpy(card->driver, DRIVER_NAME);
...@@ -367,28 +324,17 @@ static int snd_cs5535audio_probe(struct pci_dev *pci, ...@@ -367,28 +324,17 @@ static int snd_cs5535audio_probe(struct pci_dev *pci,
err = snd_card_register(card); err = snd_card_register(card);
if (err < 0) if (err < 0)
goto probefail_out; return err;
pci_set_drvdata(pci, card); pci_set_drvdata(pci, card);
dev++; dev++;
return 0; return 0;
probefail_out:
snd_card_free(card);
return err;
}
static void snd_cs5535audio_remove(struct pci_dev *pci)
{
olpc_quirks_cleanup();
snd_card_free(pci_get_drvdata(pci));
} }
static struct pci_driver cs5535audio_driver = { static struct pci_driver cs5535audio_driver = {
.name = KBUILD_MODNAME, .name = KBUILD_MODNAME,
.id_table = snd_cs5535audio_ids, .id_table = snd_cs5535audio_ids,
.probe = snd_cs5535audio_probe, .probe = snd_cs5535audio_probe,
.remove = snd_cs5535audio_remove,
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
.driver = { .driver = {
.pm = &snd_cs5535audio_pm, .pm = &snd_cs5535audio_pm,
......
...@@ -171,10 +171,8 @@ int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97) ...@@ -171,10 +171,8 @@ int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
for (i = 0; i < ARRAY_SIZE(olpc_cs5535audio_ctls); i++) { for (i = 0; i < ARRAY_SIZE(olpc_cs5535audio_ctls); i++) {
err = snd_ctl_add(card, snd_ctl_new1(&olpc_cs5535audio_ctls[i], err = snd_ctl_add(card, snd_ctl_new1(&olpc_cs5535audio_ctls[i],
ac97->private_data)); ac97->private_data));
if (err < 0) { if (err < 0)
gpio_free(OLPC_GPIO_MIC_AC);
return err; return err;
}
} }
/* turn off the mic by default */ /* turn off the mic by default */
...@@ -184,5 +182,6 @@ int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97) ...@@ -184,5 +182,6 @@ int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
void olpc_quirks_cleanup(void) void olpc_quirks_cleanup(void)
{ {
gpio_free(OLPC_GPIO_MIC_AC); if (machine_is_olpc())
gpio_free(OLPC_GPIO_MIC_AC);
} }
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