aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRene Herman <rene.herman@keyaccess.nl>2006-03-28 05:38:20 -0500
committerJaroslav Kysela <perex@suse.cz>2006-03-31 10:58:59 -0500
commitcf40a310a7aaf1944eea3e01e9c120b31850c3b6 (patch)
treea5e17b831899b2db25cd5f18b3e2f15eda0b3adf
parent060d77b9c04acd7aef60790398a53f731db8c8fe (diff)
[ALSA] AdLib FM card driver
Attached you'll find an ALSA driver for AdLib FM cards. An AdLib card is just an OPL2, which was already supported by sound/drivers/opl3, so only very minimal bus-glue is needed. The patch applies cleanly to both 2.6.16 and 2.6.16-mm1. The driver has been tested with an actual ancient 8-bit ISA AdLib card and works fine. It also works fine for an OPL3 {,emulation} as still found on many ISA soundcards but given that AdLib cards don't have their own mixer, upping the volume from 0 might be a problem without the card driver already loaded and driving the OPL3. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt28
-rw-r--r--sound/isa/Kconfig9
-rw-r--r--sound/isa/Makefile2
-rw-r--r--sound/isa/adlib.c161
4 files changed, 200 insertions, 0 deletions
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index a8c3c7e847cf..0ee2c7dfc482 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -120,6 +120,34 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
120 enable - enable card 120 enable - enable card
121 - Default: enabled, for PCI and ISA PnP cards 121 - Default: enabled, for PCI and ISA PnP cards
122 122
123 Module snd-adlib
124 ----------------
125
126 Module for AdLib FM cards.
127
128 port - port # for OPL chip
129
130 This module supports multiple cards. It does not support autoprobe, so
131 the port must be specified. For actual AdLib FM cards it will be 0x388.
132 Note that this card does not have PCM support and no mixer; only FM
133 synthesis.
134
135 Make sure you have "sbiload" from the alsa-tools package available and,
136 after loading the module, find out the assigned ALSA sequencer port
137 number through "sbiload -l". Example output:
138
139 Port Client name Port name
140 64:0 OPL2 FM synth OPL2 FM Port
141
142 Load the std.sb and drums.sb patches also supplied by sbiload:
143
144 sbiload -p 64:0 std.sb drums.sb
145
146 If you use this driver to drive an OPL3, you can use std.o3 and drums.o3
147 instead. To have the card produce sound, use aplaymidi from alsa-utils:
148
149 aplaymidi -p 64:0 foo.mid
150
123 Module snd-ad1816a 151 Module snd-ad1816a
124 ------------------ 152 ------------------
125 153
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 2a1c7334210a..557c4de22960 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -11,6 +11,15 @@ config SND_CS4231_LIB
11 tristate 11 tristate
12 select SND_PCM 12 select SND_PCM
13 13
14config SND_ADLIB
15 tristate "AdLib FM card"
16 select SND_OPL3_LIB
17 help
18 Say Y here to include support for AdLib FM cards.
19
20 To compile this driver as a module, choose M here: the module
21 will be called snd-adlib.
22
14config SND_AD1816A 23config SND_AD1816A
15 tristate "Analog Devices SoundPort AD1816A" 24 tristate "Analog Devices SoundPort AD1816A"
16 depends on SND && PNP && ISA 25 depends on SND && PNP && ISA
diff --git a/sound/isa/Makefile b/sound/isa/Makefile
index 05724eb7bfe4..bb317ccc170f 100644
--- a/sound/isa/Makefile
+++ b/sound/isa/Makefile
@@ -3,6 +3,7 @@
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> 3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4# 4#
5 5
6snd-adlib-objs := adlib.o
6snd-als100-objs := als100.o 7snd-als100-objs := als100.o
7snd-azt2320-objs := azt2320.o 8snd-azt2320-objs := azt2320.o
8snd-cmi8330-objs := cmi8330.o 9snd-cmi8330-objs := cmi8330.o
@@ -13,6 +14,7 @@ snd-sgalaxy-objs := sgalaxy.o
13snd-sscape-objs := sscape.o 14snd-sscape-objs := sscape.o
14 15
15# Toplevel Module Dependency 16# Toplevel Module Dependency
17obj-$(CONFIG_SND_ADLIB) += snd-adlib.o
16obj-$(CONFIG_SND_ALS100) += snd-als100.o 18obj-$(CONFIG_SND_ALS100) += snd-als100.o
17obj-$(CONFIG_SND_AZT2320) += snd-azt2320.o 19obj-$(CONFIG_SND_AZT2320) += snd-azt2320.o
18obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o 20obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o
diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c
new file mode 100644
index 000000000000..a253a14e6a45
--- /dev/null
+++ b/sound/isa/adlib.c
@@ -0,0 +1,161 @@
1/*
2 * AdLib FM card driver.
3 */
4
5#include <sound/driver.h>
6#include <linux/kernel.h>
7#include <linux/module.h>
8#include <linux/platform_device.h>
9#include <sound/core.h>
10#include <sound/initval.h>
11#include <sound/opl3.h>
12
13#define CRD_NAME "AdLib FM"
14#define DRV_NAME "snd_adlib"
15
16MODULE_DESCRIPTION(CRD_NAME);
17MODULE_AUTHOR("Rene Herman");
18MODULE_LICENSE("GPL");
19
20static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
21static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
22static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
23static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
24
25module_param_array(index, int, NULL, 0444);
26MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
27module_param_array(id, charp, NULL, 0444);
28MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
29module_param_array(enable, bool, NULL, 0444);
30MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
31module_param_array(port, long, NULL, 0444);
32MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
33
34static struct platform_device *devices[SNDRV_CARDS];
35
36static void snd_adlib_free(struct snd_card *card)
37{
38 release_and_free_resource(card->private_data);
39}
40
41static int __devinit snd_adlib_probe(struct platform_device *device)
42{
43 struct snd_card *card;
44 struct snd_opl3 *opl3;
45
46 int error;
47 int i = device->id;
48
49 if (port[i] == SNDRV_AUTO_PORT) {
50 snd_printk(KERN_ERR DRV_NAME ": please specify port\n");
51 error = -EINVAL;
52 goto out0;
53 }
54
55 card = snd_card_new(index[i], id[i], THIS_MODULE, 0);
56 if (!card) {
57 snd_printk(KERN_ERR DRV_NAME ": could not create card\n");
58 error = -EINVAL;
59 goto out0;
60 }
61
62 card->private_data = request_region(port[i], 4, CRD_NAME);
63 if (!card->private_data) {
64 snd_printk(KERN_ERR DRV_NAME ": could not grab ports\n");
65 error = -EBUSY;
66 goto out1;
67 }
68 card->private_free = snd_adlib_free;
69
70 error = snd_opl3_create(card, port[i], port[i] + 2, OPL3_HW_AUTO, 1, &opl3);
71 if (error < 0) {
72 snd_printk(KERN_ERR DRV_NAME ": could not create OPL\n");
73 goto out1;
74 }
75
76 error = snd_opl3_hwdep_new(opl3, 0, 0, NULL);
77 if (error < 0) {
78 snd_printk(KERN_ERR DRV_NAME ": could not create FM\n");
79 goto out1;
80 }
81
82 strcpy(card->driver, DRV_NAME);
83 strcpy(card->shortname, CRD_NAME);
84 sprintf(card->longname, CRD_NAME " at %#lx", port[i]);
85
86 snd_card_set_dev(card, &device->dev);
87
88 error = snd_card_register(card);
89 if (error < 0) {
90 snd_printk(KERN_ERR DRV_NAME ": could not register card\n");
91 goto out1;
92 }
93
94 platform_set_drvdata(device, card);
95 return 0;
96
97out1: snd_card_free(card);
98 out0: error = -EINVAL; /* FIXME: should be the original error code */
99 return error;
100}
101
102static int __devexit snd_adlib_remove(struct platform_device *device)
103{
104 snd_card_free(platform_get_drvdata(device));
105 platform_set_drvdata(device, NULL);
106 return 0;
107}
108
109static struct platform_driver snd_adlib_driver = {
110 .probe = snd_adlib_probe,
111 .remove = __devexit_p(snd_adlib_remove),
112
113 .driver = {
114 .name = DRV_NAME
115 }
116};
117
118static int __init alsa_card_adlib_init(void)
119{
120 int i, cards;
121
122 if (platform_driver_register(&snd_adlib_driver) < 0) {
123 snd_printk(KERN_ERR DRV_NAME ": could not register driver\n");
124 return -ENODEV;
125 }
126
127 for (cards = 0, i = 0; i < SNDRV_CARDS; i++) {
128 struct platform_device *device;
129
130 if (!enable[i])
131 continue;
132
133 device = platform_device_register_simple(DRV_NAME, i, NULL, 0);
134 if (IS_ERR(device))
135 continue;
136
137 devices[i] = device;
138 cards++;
139 }
140
141 if (!cards) {
142#ifdef MODULE
143 printk(KERN_ERR CRD_NAME " soundcard not found or device busy\n");
144#endif
145 platform_driver_unregister(&snd_adlib_driver);
146 return -ENODEV;
147 }
148 return 0;
149}
150
151static void __exit alsa_card_adlib_exit(void)
152{
153 int i;
154
155 for (i = 0; i < SNDRV_CARDS; i++)
156 platform_device_unregister(devices[i]);
157 platform_driver_unregister(&snd_adlib_driver);
158}
159
160module_init(alsa_card_adlib_init);
161module_exit(alsa_card_adlib_exit);