diff options
| -rw-r--r-- | sound/sparc/amd7930.c | 138 |
1 files changed, 77 insertions, 61 deletions
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index dfe9bac7fa32..ba1b2a3443d3 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c | |||
| @@ -46,6 +46,7 @@ | |||
| 46 | #include <asm/io.h> | 46 | #include <asm/io.h> |
| 47 | #include <asm/irq.h> | 47 | #include <asm/irq.h> |
| 48 | #include <asm/sbus.h> | 48 | #include <asm/sbus.h> |
| 49 | #include <asm/prom.h> | ||
| 49 | 50 | ||
| 50 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 51 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
| 51 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 52 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
| @@ -335,7 +336,6 @@ struct snd_amd7930 { | |||
| 335 | int pgain; | 336 | int pgain; |
| 336 | int mgain; | 337 | int mgain; |
| 337 | 338 | ||
| 338 | struct sbus_dev *sdev; | ||
| 339 | unsigned int irq; | 339 | unsigned int irq; |
| 340 | unsigned int regs_size; | 340 | unsigned int regs_size; |
| 341 | struct snd_amd7930 *next; | 341 | struct snd_amd7930 *next; |
| @@ -946,11 +946,9 @@ static struct snd_device_ops snd_amd7930_dev_ops = { | |||
| 946 | }; | 946 | }; |
| 947 | 947 | ||
| 948 | static int __init snd_amd7930_create(struct snd_card *card, | 948 | static int __init snd_amd7930_create(struct snd_card *card, |
| 949 | struct sbus_dev *sdev, | ||
| 950 | struct resource *rp, | 949 | struct resource *rp, |
| 951 | unsigned int reg_size, | 950 | unsigned int reg_size, |
| 952 | struct linux_prom_irqs *irq_prop, | 951 | int irq, int dev, |
| 953 | int dev, | ||
| 954 | struct snd_amd7930 **ramd) | 952 | struct snd_amd7930 **ramd) |
| 955 | { | 953 | { |
| 956 | unsigned long flags; | 954 | unsigned long flags; |
| @@ -964,7 +962,6 @@ static int __init snd_amd7930_create(struct snd_card *card, | |||
| 964 | 962 | ||
| 965 | spin_lock_init(&amd->lock); | 963 | spin_lock_init(&amd->lock); |
| 966 | amd->card = card; | 964 | amd->card = card; |
| 967 | amd->sdev = sdev; | ||
| 968 | amd->regs_size = reg_size; | 965 | amd->regs_size = reg_size; |
| 969 | 966 | ||
| 970 | amd->regs = sbus_ioremap(rp, 0, amd->regs_size, "amd7930"); | 967 | amd->regs = sbus_ioremap(rp, 0, amd->regs_size, "amd7930"); |
| @@ -975,15 +972,14 @@ static int __init snd_amd7930_create(struct snd_card *card, | |||
| 975 | 972 | ||
| 976 | amd7930_idle(amd); | 973 | amd7930_idle(amd); |
| 977 | 974 | ||
| 978 | if (request_irq(irq_prop->pri, snd_amd7930_interrupt, | 975 | if (request_irq(irq, snd_amd7930_interrupt, |
| 979 | SA_INTERRUPT | SA_SHIRQ, "amd7930", amd)) { | 976 | SA_INTERRUPT | SA_SHIRQ, "amd7930", amd)) { |
| 980 | snd_printk("amd7930-%d: Unable to grab IRQ %d\n", | 977 | snd_printk("amd7930-%d: Unable to grab IRQ %d\n", |
| 981 | dev, | 978 | dev, irq); |
| 982 | irq_prop->pri); | ||
| 983 | snd_amd7930_free(amd); | 979 | snd_amd7930_free(amd); |
| 984 | return -EBUSY; | 980 | return -EBUSY; |
| 985 | } | 981 | } |
| 986 | amd->irq = irq_prop->pri; | 982 | amd->irq = irq; |
| 987 | 983 | ||
| 988 | amd7930_enable_ints(amd); | 984 | amd7930_enable_ints(amd); |
| 989 | 985 | ||
| @@ -1017,47 +1013,21 @@ static int __init snd_amd7930_create(struct snd_card *card, | |||
| 1017 | return 0; | 1013 | return 0; |
| 1018 | } | 1014 | } |
| 1019 | 1015 | ||
| 1020 | static int __init amd7930_attach(int prom_node, struct sbus_dev *sdev) | 1016 | static int __init amd7930_attach_common(struct resource *rp, int irq) |
| 1021 | { | 1017 | { |
| 1022 | static int dev; | 1018 | static int dev_num; |
| 1023 | struct linux_prom_registers reg_prop; | ||
| 1024 | struct linux_prom_irqs irq_prop; | ||
| 1025 | struct resource res, *rp; | ||
| 1026 | struct snd_card *card; | 1019 | struct snd_card *card; |
| 1027 | struct snd_amd7930 *amd; | 1020 | struct snd_amd7930 *amd; |
| 1028 | int err; | 1021 | int err; |
| 1029 | 1022 | ||
| 1030 | if (dev >= SNDRV_CARDS) | 1023 | if (dev_num >= SNDRV_CARDS) |
| 1031 | return -ENODEV; | 1024 | return -ENODEV; |
| 1032 | if (!enable[dev]) { | 1025 | if (!enable[dev_num]) { |
| 1033 | dev++; | 1026 | dev_num++; |
| 1034 | return -ENOENT; | 1027 | return -ENOENT; |
| 1035 | } | 1028 | } |
| 1036 | 1029 | ||
| 1037 | err = prom_getproperty(prom_node, "intr", | 1030 | card = snd_card_new(index[dev_num], id[dev_num], THIS_MODULE, 0); |
| 1038 | (char *) &irq_prop, sizeof(irq_prop)); | ||
| 1039 | if (err < 0) { | ||
| 1040 | snd_printk("amd7930-%d: Firmware node lacks IRQ property.\n", dev); | ||
| 1041 | return -ENODEV; | ||
| 1042 | } | ||
| 1043 | |||
| 1044 | err = prom_getproperty(prom_node, "reg", | ||
| 1045 | (char *) ®_prop, sizeof(reg_prop)); | ||
| 1046 | if (err < 0) { | ||
| 1047 | snd_printk("amd7930-%d: Firmware node lacks register property.\n", dev); | ||
| 1048 | return -ENODEV; | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | if (sdev) { | ||
| 1052 | rp = &sdev->resource[0]; | ||
| 1053 | } else { | ||
| 1054 | rp = &res; | ||
| 1055 | rp->start = reg_prop.phys_addr; | ||
| 1056 | rp->end = rp->start + reg_prop.reg_size - 1; | ||
| 1057 | rp->flags = IORESOURCE_IO | (reg_prop.which_io & 0xff); | ||
| 1058 | } | ||
| 1059 | |||
| 1060 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | ||
| 1061 | if (card == NULL) | 1031 | if (card == NULL) |
| 1062 | return -ENOMEM; | 1032 | return -ENOMEM; |
| 1063 | 1033 | ||
| @@ -1067,10 +1037,11 @@ static int __init amd7930_attach(int prom_node, struct sbus_dev *sdev) | |||
| 1067 | card->shortname, | 1037 | card->shortname, |
| 1068 | rp->flags & 0xffL, | 1038 | rp->flags & 0xffL, |
| 1069 | rp->start, | 1039 | rp->start, |
| 1070 | irq_prop.pri); | 1040 | irq); |
| 1071 | 1041 | ||
| 1072 | if ((err = snd_amd7930_create(card, sdev, rp, reg_prop.reg_size, | 1042 | if ((err = snd_amd7930_create(card, rp, |
| 1073 | &irq_prop, dev, &amd)) < 0) | 1043 | (rp->end - rp->start) + 1, |
| 1044 | irq, dev_num, &amd)) < 0) | ||
| 1074 | goto out_err; | 1045 | goto out_err; |
| 1075 | 1046 | ||
| 1076 | if ((err = snd_amd7930_pcm(amd)) < 0) | 1047 | if ((err = snd_amd7930_pcm(amd)) < 0) |
| @@ -1085,7 +1056,8 @@ static int __init amd7930_attach(int prom_node, struct sbus_dev *sdev) | |||
| 1085 | amd->next = amd7930_list; | 1056 | amd->next = amd7930_list; |
| 1086 | amd7930_list = amd; | 1057 | amd7930_list = amd; |
| 1087 | 1058 | ||
| 1088 | dev++; | 1059 | dev_num++; |
| 1060 | |||
| 1089 | return 0; | 1061 | return 0; |
| 1090 | 1062 | ||
| 1091 | out_err: | 1063 | out_err: |
| @@ -1093,29 +1065,71 @@ out_err: | |||
| 1093 | return err; | 1065 | return err; |
| 1094 | } | 1066 | } |
| 1095 | 1067 | ||
| 1096 | static int __init amd7930_init(void) | 1068 | static int __init amd7930_obio_attach(struct device_node *dp) |
| 1069 | { | ||
| 1070 | struct linux_prom_registers *regs; | ||
| 1071 | struct linux_prom_irqs *irqp; | ||
| 1072 | struct resource res, *rp; | ||
| 1073 | int len; | ||
| 1074 | |||
| 1075 | irqp = of_get_property(dp, "intr", &len); | ||
| 1076 | if (!irqp) { | ||
| 1077 | snd_printk("%s: Firmware node lacks IRQ property.\n", | ||
| 1078 | dp->full_name); | ||
| 1079 | return -ENODEV; | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | regs = of_get_property(dp, "reg", &len); | ||
| 1083 | if (!regs) { | ||
| 1084 | snd_printk("%s: Firmware node lacks register property.\n", | ||
| 1085 | dp->full_name); | ||
| 1086 | return -ENODEV; | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | rp = &res; | ||
| 1090 | rp->start = regs->phys_addr; | ||
| 1091 | rp->end = rp->start + regs->reg_size - 1; | ||
| 1092 | rp->flags = IORESOURCE_IO | (regs->which_io & 0xff); | ||
| 1093 | |||
| 1094 | return amd7930_attach_common(rp, irqp->pri); | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | static int __devinit amd7930_sbus_probe(struct of_device *dev, const struct of_device_id *match) | ||
| 1097 | { | 1098 | { |
| 1098 | struct sbus_bus *sbus; | 1099 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); |
| 1099 | struct sbus_dev *sdev; | ||
| 1100 | int node, found; | ||
| 1101 | 1100 | ||
| 1102 | found = 0; | 1101 | return amd7930_attach_common(&sdev->resource[0], sdev->irqs[0]); |
| 1102 | } | ||
| 1103 | |||
| 1104 | static struct of_device_id amd7930_match[] = { | ||
| 1105 | { | ||
| 1106 | .name = "audio", | ||
| 1107 | }, | ||
| 1108 | {}, | ||
| 1109 | }; | ||
| 1110 | |||
| 1111 | static struct of_platform_driver amd7930_sbus_driver = { | ||
| 1112 | .name = "audio", | ||
| 1113 | .match_table = amd7930_match, | ||
| 1114 | .probe = amd7930_sbus_probe, | ||
| 1115 | }; | ||
| 1116 | |||
| 1117 | static int __init amd7930_init(void) | ||
| 1118 | { | ||
| 1119 | struct device_node *dp; | ||
| 1103 | 1120 | ||
| 1104 | /* Try to find the sun4c "audio" node first. */ | 1121 | /* Try to find the sun4c "audio" node first. */ |
| 1105 | node = prom_getchild(prom_root_node); | 1122 | dp = of_find_node_by_path("/"); |
| 1106 | node = prom_searchsiblings(node, "audio"); | 1123 | dp = dp->child; |
| 1107 | if (node && amd7930_attach(node, NULL) == 0) | 1124 | while (dp) { |
| 1108 | found++; | 1125 | if (!strcmp(dp->name, "audio")) |
| 1126 | amd7930_obio_attach(dp); | ||
| 1109 | 1127 | ||
| 1110 | /* Probe each SBUS for amd7930 chips. */ | 1128 | dp = dp->sibling; |
| 1111 | for_all_sbusdev(sdev, sbus) { | ||
| 1112 | if (!strcmp(sdev->prom_name, "audio")) { | ||
| 1113 | if (amd7930_attach(sdev->prom_node, sdev) == 0) | ||
| 1114 | found++; | ||
| 1115 | } | ||
| 1116 | } | 1129 | } |
| 1117 | 1130 | ||
| 1118 | return (found > 0) ? 0 : -EIO; | 1131 | /* Probe each SBUS for amd7930 chips. */ |
| 1132 | return of_register_driver(&amd7930_sbus_driver, &sbus_bus_type); | ||
| 1119 | } | 1133 | } |
| 1120 | 1134 | ||
| 1121 | static void __exit amd7930_exit(void) | 1135 | static void __exit amd7930_exit(void) |
| @@ -1131,6 +1145,8 @@ static void __exit amd7930_exit(void) | |||
| 1131 | } | 1145 | } |
| 1132 | 1146 | ||
| 1133 | amd7930_list = NULL; | 1147 | amd7930_list = NULL; |
| 1148 | |||
| 1149 | of_unregister_driver(&amd7930_sbus_driver); | ||
| 1134 | } | 1150 | } |
| 1135 | 1151 | ||
| 1136 | module_init(amd7930_init); | 1152 | module_init(amd7930_init); |
