summaryrefslogtreecommitdiff
path: root/sound/pci/lola/lola.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/lola/lola.c')
-rw-r--r--sound/pci/lola/lola.c209
1 files changed, 72 insertions, 137 deletions
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c
index 7307d97186cb..34a3ba17deb4 100644
--- a/sound/pci/lola/lola.c
+++ b/sound/pci/lola/lola.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Support for Digigram Lola PCI-e boards
*
* Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
- *
- * 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.
*/
#include <linux/kernel.h>
@@ -67,7 +54,6 @@ MODULE_PARM_DESC(sample_rate_min, "Minimal sample rate");
*/
MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("{{Digigram, Lola}}");
MODULE_DESCRIPTION("Digigram Lola driver");
MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
@@ -75,7 +61,7 @@ MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
static int debug;
module_param(debug, int, 0644);
#define verbose_debug(fmt, args...) \
- do { if (debug > 1) printk(KERN_DEBUG SFX fmt, ##args); } while (0)
+ do { if (debug > 1) pr_debug(SFX fmt, ##args); } while (0)
#else
#define verbose_debug(fmt, args...)
#endif
@@ -88,7 +74,6 @@ static int corb_send_verb(struct lola *chip, unsigned int nid,
unsigned int verb, unsigned int data,
unsigned int extdata)
{
- unsigned long flags;
int ret = -EIO;
chip->last_cmd_nid = nid;
@@ -97,7 +82,7 @@ static int corb_send_verb(struct lola *chip, unsigned int nid,
chip->last_extdata = extdata;
data |= (nid << 20) | (verb << 8);
- spin_lock_irqsave(&chip->reg_lock, flags);
+ guard(spinlock_irqsave)(&chip->reg_lock);
if (chip->rirb.cmds < LOLA_CORB_ENTRIES - 1) {
unsigned int wp = chip->corb.wp + 1;
wp %= LOLA_CORB_ENTRIES;
@@ -109,7 +94,6 @@ static int corb_send_verb(struct lola *chip, unsigned int nid,
smp_wmb();
ret = 0;
}
- spin_unlock_irqrestore(&chip->reg_lock, flags);
return ret;
}
@@ -168,7 +152,7 @@ static int rirb_get_response(struct lola *chip, unsigned int *val,
verbose_debug("get_response: %x, %x\n",
chip->res, chip->res_ex);
if (chip->res_ex & LOLA_RIRB_EX_ERROR) {
- printk(KERN_WARNING SFX "RIRB ERROR: "
+ dev_warn(chip->card->dev, "RIRB ERROR: "
"NID=%x, verb=%x, data=%x, ext=%x\n",
chip->last_cmd_nid,
chip->last_verb, chip->last_data,
@@ -182,9 +166,9 @@ static int rirb_get_response(struct lola *chip, unsigned int *val,
udelay(20);
cond_resched();
}
- printk(KERN_WARNING SFX "RIRB response error\n");
+ dev_warn(chip->card->dev, "RIRB response error\n");
if (!chip->polling_mode) {
- printk(KERN_WARNING SFX "switching to polling mode\n");
+ dev_warn(chip->card->dev, "switching to polling mode\n");
chip->polling_mode = 1;
goto again;
}
@@ -327,7 +311,7 @@ static int reset_controller(struct lola *chip)
break;
} while (time_before(jiffies, end_time));
if (!gctl) {
- printk(KERN_ERR SFX "cannot reset controller\n");
+ dev_err(chip->card->dev, "cannot reset controller\n");
return -EIO;
}
return 0;
@@ -358,20 +342,18 @@ static void lola_irq_disable(struct lola *chip)
static int setup_corb_rirb(struct lola *chip)
{
- int err;
unsigned char tmp;
unsigned long end_time;
- err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data(chip->pci),
- PAGE_SIZE, &chip->rb);
- if (err < 0)
- return err;
+ chip->rb = snd_devm_alloc_pages(&chip->pci->dev, SNDRV_DMA_TYPE_DEV,
+ PAGE_SIZE);
+ if (!chip->rb)
+ return -ENOMEM;
- chip->corb.addr = chip->rb.addr;
- chip->corb.buf = (u32 *)chip->rb.area;
- chip->rirb.addr = chip->rb.addr + 2048;
- chip->rirb.buf = (u32 *)(chip->rb.area + 2048);
+ chip->corb.addr = chip->rb->addr;
+ chip->corb.buf = (__le32 *)chip->rb->area;
+ chip->rirb.addr = chip->rb->addr + 2048;
+ chip->rirb.buf = (__le32 *)(chip->rb->area + 2048);
/* disable ringbuffer DMAs */
lola_writeb(chip, BAR0, RIRBCTL, 0);
@@ -452,40 +434,40 @@ static int lola_parse_tree(struct lola *chip)
err = lola_read_param(chip, 0, LOLA_PAR_VENDOR_ID, &val);
if (err < 0) {
- printk(KERN_ERR SFX "Can't read VENDOR_ID\n");
+ dev_err(chip->card->dev, "Can't read VENDOR_ID\n");
return err;
}
val >>= 16;
if (val != 0x1369) {
- printk(KERN_ERR SFX "Unknown codec vendor 0x%x\n", val);
+ dev_err(chip->card->dev, "Unknown codec vendor 0x%x\n", val);
return -EINVAL;
}
err = lola_read_param(chip, 1, LOLA_PAR_FUNCTION_TYPE, &val);
if (err < 0) {
- printk(KERN_ERR SFX "Can't read FUNCTION_TYPE for 0x%x\n", nid);
+ dev_err(chip->card->dev, "Can't read FUNCTION_TYPE\n");
return err;
}
if (val != 1) {
- printk(KERN_ERR SFX "Unknown function type %d\n", val);
+ dev_err(chip->card->dev, "Unknown function type %d\n", val);
return -EINVAL;
}
err = lola_read_param(chip, 1, LOLA_PAR_SPECIFIC_CAPS, &val);
if (err < 0) {
- printk(KERN_ERR SFX "Can't read SPECCAPS\n");
+ dev_err(chip->card->dev, "Can't read SPECCAPS\n");
return err;
}
chip->lola_caps = val;
chip->pin[CAPT].num_pins = LOLA_AFG_INPUT_PIN_COUNT(chip->lola_caps);
chip->pin[PLAY].num_pins = LOLA_AFG_OUTPUT_PIN_COUNT(chip->lola_caps);
- snd_printdd(SFX "speccaps=0x%x, pins in=%d, out=%d\n",
+ dev_dbg(chip->card->dev, "speccaps=0x%x, pins in=%d, out=%d\n",
chip->lola_caps,
chip->pin[CAPT].num_pins, chip->pin[PLAY].num_pins);
if (chip->pin[CAPT].num_pins > MAX_AUDIO_INOUT_COUNT ||
chip->pin[PLAY].num_pins > MAX_AUDIO_INOUT_COUNT) {
- printk(KERN_ERR SFX "Invalid Lola-spec caps 0x%x\n", val);
+ dev_err(chip->card->dev, "Invalid Lola-spec caps 0x%x\n", val);
return -EINVAL;
}
@@ -543,59 +525,32 @@ static void lola_stop_hw(struct lola *chip)
lola_irq_disable(chip);
}
-static void lola_free(struct lola *chip)
+static void lola_free(struct snd_card *card)
{
+ struct lola *chip = card->private_data;
+
if (chip->initialized)
lola_stop_hw(chip);
- lola_free_pcm(chip);
lola_free_mixer(chip);
- if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
- if (chip->bar[0].remap_addr)
- iounmap(chip->bar[0].remap_addr);
- if (chip->bar[1].remap_addr)
- iounmap(chip->bar[1].remap_addr);
- if (chip->rb.area)
- snd_dma_free_pages(&chip->rb);
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
- kfree(chip);
-}
-
-static int lola_dev_free(struct snd_device *device)
-{
- lola_free(device->device_data);
- return 0;
}
-static int lola_create(struct snd_card *card, struct pci_dev *pci,
- int dev, struct lola **rchip)
+static int lola_create(struct snd_card *card, struct pci_dev *pci, int dev)
{
- struct lola *chip;
+ struct lola *chip = card->private_data;
int err;
unsigned int dever;
- static struct snd_device_ops ops = {
- .dev_free = lola_dev_free,
- };
-
- *rchip = NULL;
+ void __iomem *iomem;
- err = pci_enable_device(pci);
+ err = pcim_enable_device(pci);
if (err < 0)
return err;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (!chip) {
- snd_printk(KERN_ERR SFX "cannot allocate chip\n");
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
spin_lock_init(&chip->reg_lock);
mutex_init(&chip->open_mutex);
chip->card = card;
chip->pci = pci;
chip->irq = -1;
+ card->private_free = lola_free;
chip->granularity = granularity[dev];
switch (chip->granularity) {
@@ -609,7 +564,7 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci,
chip->sample_rate_max = 192000;
break;
default:
- snd_printk(KERN_WARNING SFX
+ dev_warn(chip->card->dev,
"Invalid granularity %d, reset to %d\n",
chip->granularity, LOLA_GRANULARITY_MAX);
chip->granularity = LOLA_GRANULARITY_MAX;
@@ -618,49 +573,45 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci,
}
chip->sample_rate_min = sample_rate_min[dev];
if (chip->sample_rate_min > chip->sample_rate_max) {
- snd_printk(KERN_WARNING SFX
+ dev_warn(chip->card->dev,
"Invalid sample_rate_min %d, reset to 16000\n",
chip->sample_rate_min);
chip->sample_rate_min = 16000;
}
- err = pci_request_regions(pci, DRVNAME);
- if (err < 0) {
- kfree(chip);
- pci_disable_device(pci);
- return err;
- }
+ iomem = pcim_iomap_region(pci, 0, DRVNAME);
+ if (IS_ERR(iomem))
+ return PTR_ERR(iomem);
+ chip->bar[0].remap_addr = iomem;
chip->bar[0].addr = pci_resource_start(pci, 0);
- chip->bar[0].remap_addr = pci_ioremap_bar(pci, 0);
+
+ iomem = pcim_iomap_region(pci, 2, DRVNAME);
+ if (IS_ERR(iomem))
+ return PTR_ERR(iomem);
+
+ chip->bar[1].remap_addr = iomem;
chip->bar[1].addr = pci_resource_start(pci, 2);
- chip->bar[1].remap_addr = pci_ioremap_bar(pci, 2);
- if (!chip->bar[0].remap_addr || !chip->bar[1].remap_addr) {
- snd_printk(KERN_ERR SFX "ioremap error\n");
- err = -ENXIO;
- goto errout;
- }
pci_set_master(pci);
err = reset_controller(chip);
if (err < 0)
- goto errout;
+ return err;
- if (request_irq(pci->irq, lola_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, chip)) {
- printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq);
- err = -EBUSY;
- goto errout;
+ if (devm_request_irq(&pci->dev, pci->irq, lola_interrupt, IRQF_SHARED,
+ KBUILD_MODNAME, chip)) {
+ dev_err(chip->card->dev, "unable to grab IRQ %d\n", pci->irq);
+ return -EBUSY;
}
chip->irq = pci->irq;
- synchronize_irq(chip->irq);
+ card->sync_irq = chip->irq;
dever = lola_readl(chip, BAR1, DEVER);
chip->pcm[CAPT].num_streams = (dever >> 0) & 0x3ff;
chip->pcm[PLAY].num_streams = (dever >> 10) & 0x3ff;
chip->version = (dever >> 24) & 0xff;
- snd_printdd(SFX "streams in=%d, out=%d, version=0x%x\n",
+ dev_dbg(chip->card->dev, "streams in=%d, out=%d, version=0x%x\n",
chip->pcm[CAPT].num_streams, chip->pcm[PLAY].num_streams,
chip->version);
@@ -669,41 +620,29 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci,
chip->pcm[PLAY].num_streams > MAX_STREAM_OUT_COUNT ||
(!chip->pcm[CAPT].num_streams &&
!chip->pcm[PLAY].num_streams)) {
- printk(KERN_ERR SFX "invalid DEVER = %x\n", dever);
- err = -EINVAL;
- goto errout;
+ dev_err(chip->card->dev, "invalid DEVER = %x\n", dever);
+ return -EINVAL;
}
err = setup_corb_rirb(chip);
if (err < 0)
- goto errout;
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- snd_printk(KERN_ERR SFX "Error creating device [card]!\n");
- goto errout;
- }
+ return err;
- strcpy(card->driver, "Lola");
- strlcpy(card->shortname, "Digigram Lola", sizeof(card->shortname));
+ strscpy(card->driver, "Lola");
+ strscpy(card->shortname, "Digigram Lola", sizeof(card->shortname));
snprintf(card->longname, sizeof(card->longname),
"%s at 0x%lx irq %i",
card->shortname, chip->bar[0].addr, chip->irq);
- strcpy(card->mixername, card->shortname);
+ strscpy(card->mixername, card->shortname);
lola_irq_enable(chip);
chip->initialized = 1;
- *rchip = chip;
return 0;
-
- errout:
- lola_free(chip);
- return err;
}
-static int lola_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int __lola_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
@@ -717,52 +656,49 @@ static int lola_probe(struct pci_dev *pci,
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) {
- snd_printk(KERN_ERR SFX "Error creating card!\n");
+ dev_err(&pci->dev, "Error creating card!\n");
return err;
}
+ chip = card->private_data;
- snd_card_set_dev(card, &pci->dev);
-
- err = lola_create(card, pci, dev, &chip);
+ err = lola_create(card, pci, dev);
if (err < 0)
- goto out_free;
- card->private_data = chip;
+ return err;
err = lola_parse_tree(chip);
if (err < 0)
- goto out_free;
+ return err;
err = lola_create_pcm(chip);
if (err < 0)
- goto out_free;
+ return err;
err = lola_create_mixer(chip);
if (err < 0)
- goto out_free;
+ return err;
lola_proc_debug_new(chip);
err = snd_card_register(card);
if (err < 0)
- goto out_free;
+ return err;
pci_set_drvdata(pci, card);
dev++;
- return err;
-out_free:
- snd_card_free(card);
- return err;
+ return 0;
}
-static void lola_remove(struct pci_dev *pci)
+static int lola_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, __lola_probe(pci, pci_id));
}
/* PCI IDs */
-static DEFINE_PCI_DEVICE_TABLE(lola_ids) = {
+static const struct pci_device_id lola_ids[] = {
{ PCI_VDEVICE(DIGIGRAM, 0x0001) },
{ 0, }
};
@@ -773,7 +709,6 @@ static struct pci_driver lola_driver = {
.name = KBUILD_MODNAME,
.id_table = lola_ids,
.probe = lola_probe,
- .remove = lola_remove,
};
module_pci_driver(lola_driver);