ALSA: snd-usb-caiaq: Simplify single case to an 'if'
[safe/jmp/linux-2.6] / sound / sparc / amd7930.c
index c271049..574af56 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Driver for AMD7930 sound chips found on Sparcs.
- * Copyright (C) 2002 David S. Miller <davem@redhat.com>
+ * Copyright (C) 2002, 2008 David S. Miller <davem@davemloft.net>
  *
  * Based entirely upon drivers/sbus/audio/amd7930.c which is:
  * Copyright (C) 1996,1997 Thomas K. Dyas (tdyas@eden.rutgers.edu)
@@ -35,8 +35,9 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/moduleparam.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
-#include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/info.h>
@@ -45,7 +46,7 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/sbus.h>
+#include <asm/prom.h>
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;      /* ID for this card */
@@ -335,9 +336,8 @@ struct snd_amd7930 {
        int                     pgain;
        int                     mgain;
 
-       struct sbus_dev         *sdev;
+       struct of_device        *op;
        unsigned int            irq;
-       unsigned int            regs_size;
        struct snd_amd7930      *next;
 };
 
@@ -491,7 +491,7 @@ static void __amd7930_update_map(struct snd_amd7930 *amd)
        __amd7930_write_map(amd);
 }
 
-static irqreturn_t snd_amd7930_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t snd_amd7930_interrupt(int irq, void *dev_id)
 {
        struct snd_amd7930 *amd = dev_id;
        unsigned int elapsed;
@@ -755,7 +755,7 @@ static struct snd_pcm_ops snd_amd7930_capture_ops = {
        .pointer        =       snd_amd7930_capture_pointer,
 };
 
-static int __init snd_amd7930_pcm(struct snd_amd7930 *amd)
+static int __devinit snd_amd7930_pcm(struct snd_amd7930 *amd)
 {
        struct snd_pcm *pcm;
        int err;
@@ -766,7 +766,6 @@ static int __init snd_amd7930_pcm(struct snd_amd7930 *amd)
                               /* playback count */ 1,
                               /* capture count */  1, &pcm)) < 0)
                return err;
-       snd_assert(pcm != NULL, return -EINVAL);
 
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_amd7930_playback_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_amd7930_capture_ops);
@@ -789,13 +788,6 @@ static int __init snd_amd7930_pcm(struct snd_amd7930 *amd)
 
 static int snd_amd7930_info_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo)
 {
-       int type = kctl->private_value;
-
-       snd_assert(type == VOLUME_MONITOR ||
-                  type == VOLUME_CAPTURE ||
-                  type == VOLUME_PLAYBACK, return -EINVAL);
-       (void) type;
-
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
        uinfo->count = 1;
        uinfo->value.integer.min = 0;
@@ -810,10 +802,6 @@ static int snd_amd7930_get_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem
        int type = kctl->private_value;
        int *swval;
 
-       snd_assert(type == VOLUME_MONITOR ||
-                  type == VOLUME_CAPTURE ||
-                  type == VOLUME_PLAYBACK, return -EINVAL);
-
        switch (type) {
        case VOLUME_MONITOR:
                swval = &amd->mgain;
@@ -839,10 +827,6 @@ static int snd_amd7930_put_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem
        int type = kctl->private_value;
        int *swval, change;
 
-       snd_assert(type == VOLUME_MONITOR ||
-                  type == VOLUME_CAPTURE ||
-                  type == VOLUME_PLAYBACK, return -EINVAL);
-
        switch (type) {
        case VOLUME_MONITOR:
                swval = &amd->mgain;
@@ -859,7 +843,7 @@ static int snd_amd7930_put_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem
        spin_lock_irqsave(&amd->lock, flags);
 
        if (*swval != ucontrol->value.integer.value[0]) {
-               *swval = ucontrol->value.integer.value[0];
+               *swval = ucontrol->value.integer.value[0] & 0xff;
                __amd7930_update_map(amd);
                change = 1;
        } else
@@ -870,7 +854,7 @@ static int snd_amd7930_put_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem
        return change;
 }
 
-static struct snd_kcontrol_new amd7930_controls[] __initdata = {
+static struct snd_kcontrol_new amd7930_controls[] __devinitdata = {
        {
                .iface          =       SNDRV_CTL_ELEM_IFACE_MIXER,
                .name           =       "Monitor Volume",
@@ -900,12 +884,13 @@ static struct snd_kcontrol_new amd7930_controls[] __initdata = {
        },
 };
 
-static int __init snd_amd7930_mixer(struct snd_amd7930 *amd)
+static int __devinit snd_amd7930_mixer(struct snd_amd7930 *amd)
 {
        struct snd_card *card;
        int idx, err;
 
-       snd_assert(amd != NULL && amd->card != NULL, return -EINVAL);
+       if (snd_BUG_ON(!amd || !amd->card))
+               return -EINVAL;
 
        card = amd->card;
        strcpy(card->mixername, card->shortname);
@@ -921,13 +906,16 @@ static int __init snd_amd7930_mixer(struct snd_amd7930 *amd)
 
 static int snd_amd7930_free(struct snd_amd7930 *amd)
 {
+       struct of_device *op = amd->op;
+
        amd7930_idle(amd);
 
        if (amd->irq)
                free_irq(amd->irq, amd);
 
        if (amd->regs)
-               sbus_iounmap(amd->regs, amd->regs_size);
+               of_iounmap(&op->resource[0], amd->regs,
+                          resource_size(&op->resource[0]));
 
        kfree(amd);
 
@@ -945,16 +933,13 @@ static struct snd_device_ops snd_amd7930_dev_ops = {
        .dev_free       =       snd_amd7930_dev_free,
 };
 
-static int __init snd_amd7930_create(struct snd_card *card,
-                                    struct sbus_dev *sdev,
-                                    struct resource *rp,
-                                    unsigned int reg_size,
-                                    struct linux_prom_irqs *irq_prop,
-                                    int dev,
-                                    struct snd_amd7930 **ramd)
+static int __devinit snd_amd7930_create(struct snd_card *card,
+                                       struct of_device *op,
+                                       int irq, int dev,
+                                       struct snd_amd7930 **ramd)
 {
-       unsigned long flags;
        struct snd_amd7930 *amd;
+       unsigned long flags;
        int err;
 
        *ramd = NULL;
@@ -964,26 +949,26 @@ static int __init snd_amd7930_create(struct snd_card *card,
 
        spin_lock_init(&amd->lock);
        amd->card = card;
-       amd->sdev = sdev;
-       amd->regs_size = reg_size;
+       amd->op = op;
 
-       amd->regs = sbus_ioremap(rp, 0, amd->regs_size, "amd7930");
+       amd->regs = of_ioremap(&op->resource[0], 0,
+                              resource_size(&op->resource[0]), "amd7930");
        if (!amd->regs) {
-               snd_printk("amd7930-%d: Unable to map chip registers.\n", dev);
+               snd_printk(KERN_ERR
+                          "amd7930-%d: Unable to map chip registers.\n", dev);
                return -EIO;
        }
 
        amd7930_idle(amd);
 
-       if (request_irq(irq_prop->pri, snd_amd7930_interrupt,
-                       SA_INTERRUPT | SA_SHIRQ, "amd7930", amd)) {
-               snd_printk("amd7930-%d: Unable to grab IRQ %s\n",
-                          dev,
-                          __irq_itoa(irq_prop->pri));
+       if (request_irq(irq, snd_amd7930_interrupt,
+                       IRQF_DISABLED | IRQF_SHARED, "amd7930", amd)) {
+               snd_printk(KERN_ERR "amd7930-%d: Unable to grab IRQ %d\n",
+                          dev, irq);
                snd_amd7930_free(amd);
                return -EBUSY;
        }
-       amd->irq = irq_prop->pri;
+       amd->irq = irq;
 
        amd7930_enable_ints(amd);
 
@@ -1017,60 +1002,38 @@ static int __init snd_amd7930_create(struct snd_card *card,
        return 0;
 }
 
-static int __init amd7930_attach(int prom_node, struct sbus_dev *sdev)
+static int __devinit amd7930_sbus_probe(struct of_device *op, const struct of_device_id *match)
 {
-       static int dev;
-       struct linux_prom_registers reg_prop;
-       struct linux_prom_irqs irq_prop;
-       struct resource res, *rp;
+       struct resource *rp = &op->resource[0];
+       static int dev_num;
        struct snd_card *card;
        struct snd_amd7930 *amd;
-       int err;
+       int err, irq;
 
-       if (dev >= SNDRV_CARDS)
-               return -ENODEV;
-       if (!enable[dev]) {
-               dev++;
-               return -ENOENT;
-       }
-
-       err = prom_getproperty(prom_node, "intr",
-                              (char *) &irq_prop, sizeof(irq_prop));
-       if (err < 0) {
-               snd_printk("amd7930-%d: Firmware node lacks IRQ property.\n", dev);
-               return -ENODEV;
-       }
+       irq = op->irqs[0];
 
-       err = prom_getproperty(prom_node, "reg",
-                              (char *) &reg_prop, sizeof(reg_prop));
-       if (err < 0) {
-               snd_printk("amd7930-%d: Firmware node lacks register property.\n", dev);
+       if (dev_num >= SNDRV_CARDS)
                return -ENODEV;
+       if (!enable[dev_num]) {
+               dev_num++;
+               return -ENOENT;
        }
 
-       if (sdev) {
-               rp = &sdev->resource[0];
-       } else {
-               rp = &res;
-               rp->start = reg_prop.phys_addr;
-               rp->end = rp->start + reg_prop.reg_size - 1;
-               rp->flags = IORESOURCE_IO | (reg_prop.which_io & 0xff);
-       }
-
-       card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-       if (card == NULL)
-               return -ENOMEM;
+       err = snd_card_create(index[dev_num], id[dev_num], THIS_MODULE, 0,
+                             &card);
+       if (err < 0)
+               return err;
 
        strcpy(card->driver, "AMD7930");
        strcpy(card->shortname, "Sun AMD7930");
-       sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %s",
+       sprintf(card->longname, "%s at 0x%02lx:0x%08Lx, irq %d",
                card->shortname,
                rp->flags & 0xffL,
-               rp->start,
-               __irq_itoa(irq_prop.pri));
+               (unsigned long long)rp->start,
+               irq);
 
-       if ((err = snd_amd7930_create(card, sdev, rp, reg_prop.reg_size,
-                                         &irq_prop, dev, &amd)) < 0)
+       if ((err = snd_amd7930_create(card, op,
+                                     irq, dev_num, &amd)) < 0)
                goto out_err;
 
        if ((err = snd_amd7930_pcm(amd)) < 0)
@@ -1079,16 +1042,14 @@ static int __init amd7930_attach(int prom_node, struct sbus_dev *sdev)
        if ((err = snd_amd7930_mixer(amd)) < 0)
                goto out_err;
 
-       if ((err = snd_card_set_generic_dev(card)) < 0)
-               goto out_err;
-
        if ((err = snd_card_register(card)) < 0)
                goto out_err;
 
        amd->next = amd7930_list;
        amd7930_list = amd;
 
-       dev++;
+       dev_num++;
+
        return 0;
 
 out_err:
@@ -1096,29 +1057,22 @@ out_err:
        return err;
 }
 
+static const struct of_device_id amd7930_match[] = {
+       {
+               .name = "audio",
+       },
+       {},
+};
+
+static struct of_platform_driver amd7930_sbus_driver = {
+       .name           = "audio",
+       .match_table    = amd7930_match,
+       .probe          = amd7930_sbus_probe,
+};
+
 static int __init amd7930_init(void)
 {
-       struct sbus_bus *sbus;
-       struct sbus_dev *sdev;
-       int node, found;
-
-       found = 0;
-
-       /* Try to find the sun4c "audio" node first. */
-       node = prom_getchild(prom_root_node);
-       node = prom_searchsiblings(node, "audio");
-       if (node && amd7930_attach(node, NULL) == 0)
-               found++;
-
-       /* Probe each SBUS for amd7930 chips. */
-       for_all_sbusdev(sdev, sbus) {
-               if (!strcmp(sdev->prom_name, "audio")) {
-                       if (amd7930_attach(sdev->prom_node, sdev) == 0)
-                               found++;
-               }
-       }
-
-       return (found > 0) ? 0 : -EIO;
+       return of_register_driver(&amd7930_sbus_driver, &of_bus_type);
 }
 
 static void __exit amd7930_exit(void)
@@ -1134,6 +1088,8 @@ static void __exit amd7930_exit(void)
        }
 
        amd7930_list = NULL;
+
+       of_unregister_driver(&amd7930_sbus_driver);
 }
 
 module_init(amd7930_init);